ZOJ 4110 Strings in the Pocket (马拉车+回文串)

时间:2024-08-01 16:04:20

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4110


题目:

BaoBao has just found two strings  and  in his left pocket, where  indicates the -th character in string , and  indicates the -th character in string .

As BaoBao is bored, he decides to select a substring of  and reverse it. Formally speaking, he can select two integers  and  such that  and change the string to .

In how many ways can BaoBao change  to  using the above operation exactly once? Let  be an operation which reverses the substring , and  be an operation which reverses the substring . These two operations are considered different, if  or .

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains a string  (), while the second line contains another string  (). Both strings are composed of lower-cased English letters.

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

2
abcbcdcbd
abcdcbcbd
abc
abc

Sample Output

3
3

Hint

For the first sample test case, BaoBao can do one of the following three operations: (2, 8), (3, 7) or (4, 6).

For the second sample test case, BaoBao can do one of the following three operations: (1, 1), (2, 2) or (3, 3).


题意:

存在S串和T串 要求对S串的一个子串做一次翻转操作可以得到T串的方案数

思路:

对子串分两种情况

第一种是S串和T串完全相同 可以的方案数就是S串中的所有的回文子串 因为S串长度为2e6 必须要用马拉车线性去处理出所有的回文子串

第二种是S串和T串有不同的部分 找出两个不同的字符最远的位置(l,r) 先判断S串的这个区间是否能通过翻转变成T串的区间 如果不可以直接输出0 如果可以 则向两侧同时延展寻找是否可以翻转


代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=2e6+;
int t,len[maxn*];
char S[maxn],T[maxn],s[maxn*]; int init(char *str){
int n=strlen(str);
for(int i=,j=;i<=*n;j++,i+=){
s[i]='#';
s[i+]=str[j];
}
s[]='$';
s[*n+]='#';
s[*n+]='@';
s[*n+]='\n';
return *n+;
} void manacher(int n){
int mx=,p=;
for(int i=;i<=n;i++){
if(mx>i) len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]]) len[i]++;
if(len[i]+i>mx) mx=len[i]+i,p=i;
}
} int main(){
scanf("%d",&t);
while(t--){
scanf("%s",S);
scanf("%s",T);
int Len=strlen(S),tot1=-,tot2=Len;
for(int i=;i<Len;i++){
if(S[i]!=T[i]){
tot1=i;break;
}
}
for(int i=Len-;i>=;i--){
if(S[i]!=T[i]){
tot2=i;break;
}
}
if(tot1==-){
int n=init(S);
for(int i=;i<=n;i++) len[i]=;
manacher(n);
ll ans=;
for(int i=;i<=n;i++) ans+=len[i]/;
printf("%lld\n",ans);
continue;
}
else{
int tmp=;
for(int i=tot1;i<=tot2;i++){
if(S[i]!=T[tot2-(i-tot1)]){
tmp=;
break;
}
}
if(tmp==){
printf("0\n");
continue;
}
else{
ll ans=; tot1--; tot2++;
while (tot1>= && tot2<Len && S[tot1]==T[tot2] && S[tot2]==T[tot1]){
tot1--; tot2++; ans++;
}
printf("%lld\n",ans);
}
}
}
return ;
}