题目大意:给出一个字符串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;
}