0
点赞
收藏
分享

微信扫一扫

ZOJ Problem- 4110 Strings in the Pocket(马拉车求回文串的个数)


K Strings in the Pocket
Time Limit: 1 Second      Memory Limit: 65536 KB

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的区间(l,r)反转,问有多少种方法?

分析:

关键对于两个字符串相等的情况,马拉车算法求回文子串的个数就ok

不相等的话,直接暴力找到s和t不相同的位置,然后判断反转后能不能相等,不相等直接就0,相等的话,就一此为基础扩展(只要(l,r)两边的字符相等就ok。

#include <bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=2000005;
char s[maxn],t[maxn];
char str[maxn];//原字符串
char tmp[maxn<<1];//转换后的字符串
int Len[maxn<<1];
//转换原始串
int init(char *st)
{
int i,len=strlen(st);
tmp[0]='@';//字符串开头增加一个特殊字符,防止越界
for(i=1; i<=2*len; i+=2)
{
tmp[i]='#';
tmp[i+1]=st[i/2];
}
tmp[2*len+1]='#';
tmp[2*len+2]='$';//字符串结尾加一个字符,防止越界
tmp[2*len+3]=0;
return 2*len+1;//返回转换字符串的长度
}
//Manacher算法计算过程
ll manacher(char *st,int len)
{
int mx=0,ans=0,po=0;//mx即为当前计算回文串最右边字符的最大值
ll num=0;
for(int i=1; i<=len; i++)
{
if(mx>i)
Len[i]=min(mx-i,Len[2*po-i]);//在Len[j]和mx-i中取个小
else
Len[i]=1;//如果i>=mx,要从头开始匹配

while(st[i-Len[i]]==st[i+Len[i]])
Len[i]++;
if(Len[i]+i>mx)//若新计算的回文串右端点位置大于mx,要更新po和mx的值
{
mx=Len[i]+i;
po=i;
}
int l=(i-1)/2-(Len[i]-1)/2;
int r=(i-1)/2+(Len[i]-1)/2;
if(Len[i]&1)
r--;

num+=((r-l+2)/2);
ans=max(ans,Len[i]);
}
return num; //返回回文子串的个数
return ans-1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度
}
int main()
{
int T;
scanf("%d",&T);
int l,r;
while(T--)
{
ll ans=0;
scanf("%s%s",s,t);
int n=strlen(s);
l=-1;
for(int i=0; i<n; i++)
{
if(s[i]!=t[i])
{
l=i;
break;
}
}
if(l!=-1)
{
r=-1;
for(int i=n-1; i>=0; i--)
{
if(s[i]!=t[i])
{
r=i;
break;
}
}
int j=r,flag=0;
for(int i=l; i<=r; i++,j--)
{
if(s[i]!=t[j])
{
flag=1;
break;
}
}
if(flag)
{
printf("0\n");
}
else
{
ans=1;
for(int i=1; i<=l&&r+i<n; i++)
{
if(s[l-i]==s[r+i])
ans++;
else
break;
}
printf("%lld\n",ans);
}
}
else///s==t的时候
{
int len=init(s);
cout<<manacher(tmp,len)<<endl;
}
}
}

 
 

举报

相关推荐

最长回文子串(马拉车算法)

0 条评论