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串,能够反转的区间个数是多少;(或者叫做交换更好理解一点)
分析:这里需要注意两种情况
1.当两个字符串字符相等的时候,你需要求一下这两个字符串的回文串的长度,其实在这题当中需要用到的是Manacher中Len数组(Len数组定义就是以当前字符能够达到的回文字符串的半径?,这里还要包括其本身,不同的博客定义可能不相同,但是意义都是一样的),通过这个字符串就能求出反转的子字符串的长度
2.当两个字符串不是相同的时候,你需要找到这个S串中最左和最右不相等的端点,然后看这个区间里面的字符是否符合反转要求,如果里面的字符反转后不相等,那么就输出0,否则的话就以这两个端点向两端去扩展,扩展的话只有是相等的字符才行;
什么意思呢???
比如这个字符串
aabacbab
aabcabab这两个只能是扩展到第二个字符就截止,但如果是下面这种情况:
aabacbaa
aabcabaa
这样就能扩展到第一个字符(上下两种都是从下标1开始的,别混了?)
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <set>
#include <stack>
using namespace std;
typedef long long ll;
const int N = 2e6+100;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Abs(x) ((x)>=0?(x):-(x))
char str1[N],str2[N],str[3*N];
int vis[N],Len[N*3];
void init(int x){
int k=0;
Len[k]=0;str[k++]='$';
int len=strlen(str1);
for(int i=x;i<len;i++){
Len[k]=0;str[k++]='#';
Len[k]=0;str[k++]=str1[i];
}
Len[k]=0;str[k++]='#';
Len[k]=0;str[k++]='\0';
}
int Manacher(){
Len[0]=0;
int mx=0,id=0;
int len=strlen(str);
for(int i=0;i<len;i++){
if(i<mx)
Len[i]=min(mx-i,Len[2*id-i]);
else
Len[i]=1;
while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++;
if(Len[i]+i>mx){
mx=Len[i]+i;
id=i;
}
}
// printf("Len数组:\n");
// for(int i=0;i<len;i++){
// printf("%d ",Len[i]);
// }
// printf("\n");
return len;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int t;
scanf("%d\n",&t);
while(t--){
scanf("%s%s",str1,str2);
int len=strlen(str1);
if(strcmp(str1,str2)==0){
init(0);
ll ans=0;
int k=Manacher();
for(int i=0;i<k;i++) ans+=Len[i]/2;
printf("%lld\n",ans);
continue;
}
int cnt=0;
for(int i=0;i<len;i++){
if(str1[i]!=str2[i]) vis[cnt++]=i;
}
if(cnt&1) { printf("0\n"); continue;}//当存在奇数个不同的字符的时候,肯定是不管是怎么交换都是不满足题意的
int flag=0;
for(int i=vis[0],j=vis[cnt-1];i<j;i++,j--){
if(str1[j]!=str2[i]||str1[i]!=str2[j]){
flag=1;break;
}
}
if(flag) {printf("0\n");continue;}
int ans=1;
for(int i=vis[0]-1,j=vis[cnt-1]+1;i>=0&&j<len;i--,j++){
if(str1[i]==str2[j]&&str2[j]==str1[i]) ans++;
else break;
}
printf("%d\n",ans);
}
return 0;
}