Problem - D - Codeforces
题目大意:给出一个字符串s,s中可能存在能代表任意字母的?,如果一个长度为偶数的子串的前一半字母和后一半字母完全相同,则称这个子串合法,求s中最长的合法子串的长度
2<=字符串长度<=5000
思路:要找这样的合法子串相当于找一个长度为len子串str,使得这个子串,后面的len个字母组成的字符串和str相同,所以我们首先要确定的就是这样的Str的长度。
假设我们已经确定了当前要匹配的str的长度为len,那么要做的就是当前位置i和i+len的位置进行匹配,如果能匹配就就分别后移两个指针,直到匹配的字母数等于len,如果不匹配,因为要匹配的位置都是固定好的,所以下一个要匹配的位置就是失配位置的下一个位置。
那么对于一个固定的len,所以要查找一个合法的子串的时间复杂度是O(n)的,那么就可以遍历长度再找合法子串了。
注意因为有?所以要重定义字符相等的规则
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
const ll MOD = 1e9 + 7;
ll n;
bool equal(char x, char y)
{if (x == y || x == '?' || y == '?'){//两字母相等或者其中之一是?就是相等return 1;}return 0;
}
void init()
{}
void solve()
{init();string str;cin >> str;n = str.length();int ans = 0;for (int len = n/2; len >= 1; len--){//枚举合法子串一半的长度int cnt = 0;for (int i = 0; i < n - len; i++){ int j = i + len;if (equal(str[i], str[j])){cnt++;//记录匹配的位置的数量 }else{cnt = 0;//否则重置匹配的位置数量,尝试匹配下一个位置}if (cnt == len){//匹配的位置等于长度,直接输出答案cout << cnt * 2 << '\n';return;}}}cout << ans;cout << '\n';
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);int t;cin >> t;while (t--){solve();}return 0;
}