UVALive - 7041 The Problem to Slow Down You (回文树+dfs)

匿名 (未验证) 提交于 2019-12-03 00:03:02

题意:

给两个字符串S、T
问有多少对子串A、B
满足A属于S串、B属于T串
且A==B同时A是回文串

分析:

对两个串建两个回文树,然后dfs求相同的回文串

当匹配到的时候
假设A串出现x次,B串出现y次
因为可以互相匹配所以答案累加xy

code:

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int maxm=3e5+5; struct Pam{     int nt[maxm][26];//下一个节点     int fail[maxm];//失配指针     int cnt[maxm];//节点i表示的本质不同的串的个数(最后cal完才是准确的)     int num[maxm];//节点i表示的回文串的回文后缀个数     int len[maxm];//节点i表示的回文串长度     int s[maxm];//存放添加的字符     int last;//新添加一个字母后所形成的最长回文串对应节点     int n;//添加的字符数,也是s数组的长度     int p;//节点指针,表示节点数量     int newnode(int x){//创建新节点         for(int i=0;i<26;i++){             nt[p][i]=0;         }         cnt[p]=num[p]=0;         len[p]=x;//长度为x         return p++;     }     void init(){//初始化         p=n=last=0;         newnode(0);//偶数长度树         newnode(-1);//奇数长度树         s[n]=-1;//设置第一个字符为-1(也可以是其他不可能被匹配的字符)         fail[0]=1;     }     int getfail(int x){//利用fail找到匹配的节点         while(s[n-len[x]-1]!=s[n])x=fail[x];         return x;     }     void add(int c){         c-='a';         s[++n]=c;         int cur=getfail(last);         if(!nt[cur][c]){//如果没有就新建一个节点             int now=newnode(len[cur]+2);//从cur拓展而来             fail[now]=nt[getfail(fail[cur])][c];             nt[cur][c]=now;             num[now]=num[fail[now]]+1;         }         last=nt[cur][c];         cnt[last]++;     }     void cal(){         for(int i=p-1;i>=0;i--){             cnt[fail[i]]+=cnt[i];         }     } }p,pp; char s[maxm],t[maxm]; ll dfs(int a,int b){     ll ans=0;     for(int i=0;i<26;i++){         int aa=p.nt[a][i],bb=pp.nt[b][i];         if(aa&&bb){             ans+=(ll)p.cnt[aa]*pp.cnt[bb]+dfs(aa,bb);//注意p.cnt[]是int型的要转long long再相乘         }     }     return ans; } int main(){     int T;     scanf("%d",&T);     int cas=1;     while(T--){         p.init();         pp.init();         scanf("%s%s",s,t);         for(int i=0;s[i];i++){             p.add(s[i]);         }         for(int i=0;t[i];i++){             pp.add(t[i]);         }         p.cal();         pp.cal();         ll ans=dfs(0,0)+dfs(1,1);         printf("Case #%d: %lld\n",cas++,ans);     }     return 0; } 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!