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

链接: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+100;
int t,len[maxn*2];
char S[maxn],T[maxn],s[maxn*2];

int init(char *str){
    int n=strlen(str);
    for(int i=1,j=0;i<=2*n;j++,i+=2){
        s[i]='#';
        s[i+1]=str[j];
    }
    s[0]='$';
    s[2*n+1]='#';
    s[2*n+2]='@';
    s[2*n+3]='\n';
    return 2*n+1;
}

void manacher(int n){
    int mx=0,p=0;
    for(int i=1;i<=n;i++){
        if(mx>i) len[i]=min(mx-i,len[2*p-i]);
        else len[i]=1;
        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=-1,tot2=Len;
        for(int i=0;i<Len;i++){
            if(S[i]!=T[i]){
                tot1=i;break;
            } 
        }
        for(int i=Len-1;i>=0;i--){
            if(S[i]!=T[i]){
                tot2=i;break;
            }
        }
        if(tot1==-1){
            int n=init(S);
            for(int i=0;i<=n;i++) len[i]=0;
            manacher(n);
            ll ans=0;
            for(int i=1;i<=n;i++) ans+=len[i]/2;
            printf("%lld\n",ans);
            continue;
        }
        else{
            int tmp=0;
            for(int i=tot1;i<=tot2;i++){
                if(S[i]!=T[tot2-(i-tot1)]){
                    tmp=1;
                    break;
                }
            }
            if(tmp==1){
                printf("0\n"); 
                continue;
            }
            else{
                ll ans=1; tot1--; tot2++;
                while (tot1>=0 && tot2<Len && S[tot1]==T[tot2] && S[tot2]==T[tot1]){
                        tot1--; tot2++; ans++;
                }
                printf("%lld\n",ans);
            }
        }
    }
    return 0; 
} 

 

posted @ 2019-04-28 19:16  周园顾  阅读(1094)  评论(0编辑  收藏  举报