Finding Palindromes
题意:给n个串,任意两个组合,有n*n种组合,问有多少种是回文串。
Trie树+扩展KMP。。。
我用的LRJ的Trie树模板超内存=_=||
又用了带指针的那种~
时隔五个月的一道题,今天终于干掉了=_=||
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int maxnode=2000010; 5 const int sigma=26; 6 #define ll long long 7 int bg[maxnode],ed[maxnode]; 8 char s[maxnode],t[maxnode]; 9 int flag[2][maxnode]; 10 int len; 11 int nex[maxnode],ex[maxnode]; 12 13 14 struct Node{ 15 Node* ch[sigma]; 16 int v1,v2; 17 }; 18 Node node[maxnode]; 19 int cnt; 20 Node* rt; 21 ll ans; 22 23 void insert_(char* s,int l,int r){ 24 Node* temp=rt; 25 for(int i=l;i<r;i++){ 26 int c=s[i]-'a'; 27 temp->v1+=flag[0][i]; 28 if(temp->ch[c]==NULL ) temp->ch[c]=&node[cnt++]; 29 temp=temp->ch[c]; 30 } 31 (temp->v2)++; 32 } 33 void query(char* s,int l,int r){ 34 Node* temp=rt; 35 for(int i=l;i<r;i++){ 36 int c=s[i]-'a'; 37 temp=temp->ch[c]; 38 if(temp==NULL) break; 39 if(i<r-1&&flag[1][i+1]||i==r-1) ans+=temp->v2; 40 } 41 if(temp) ans+=temp->v1; 42 } 43 44 void getnex(char* t,int l,int r){ 45 nex[l]=r-l; 46 int a=0,p=0; 47 for(int i=1;i<r-l;i++){ 48 if(i>=p||i+nex[i-a+l]>=p){ 49 if(i>=p) p=i; 50 while(p<r-l&&t[p+l]==t[p-i+l]) p++; 51 nex[i+l]=p-i; 52 a=i; 53 }else nex[i+l]=nex[i-a+l]; 54 } 55 } 56 57 void exkmp(char* s,char* t,int l,int r,int b){ 58 getnex(t,l,r); 59 int a=0,p=0; 60 for(int i=0;i<r-l;i++){ 61 if(i>=p||i+nex[i-a+l]>=p){ 62 if(i>=p) p=i; 63 while(p<r-l&&s[p+l]==t[p-i+l]) p++; 64 ex[i+l]=p-i; 65 a=i; 66 }else ex[i+l]=nex[i-a+l]; 67 } 68 for(int i=l;i<r;i++){ 69 if(i+ex[i]==r) flag[b][i]=1; 70 } 71 } 72 73 int main(){ 74 int n; 75 while(scanf("%d",&n)!=EOF){ 76 cnt=0; 77 ans=0; 78 memset(node,0,sizeof(node)); 79 memset(flag,0,sizeof(flag)); 80 rt=&node[cnt++]; 81 int L=0; 82 for(int i=0;i<n;i++){ 83 scanf("%d%s",&len,s+L); 84 bg[i]=L;ed[i]=L+len; 85 for(int j=0;j<len;j++) t[j+L]=s[L+len-j-1]; 86 L+=len; 87 exkmp(s,t,bg[i],ed[i],0); 88 exkmp(t,s,bg[i],ed[i],1); 89 insert_(s,bg[i],ed[i]); 90 } 91 for(int i=0;i<n;i++) { 92 query(t,bg[i],ed[i]); 93 } 94 printf("%lld ",ans); 95 } 96 return 0; 97 }
补上用前向星存边的Trie树,内存省了好多~也快了一倍~
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int maxnode=2000010; 5 const int sigma=26; 6 #define ll long long 7 int bg[maxnode],ed[maxnode]; 8 char s[maxnode],t[maxnode]; 9 int flag[2][maxnode]; 10 int len; 11 int nex[maxnode],ex[maxnode]; 12 13 //Trie树 14 struct Trie{ 15 int head[maxnode],nex[maxnode]; 16 int v1[maxnode],v2[maxnode]; 17 char ch[maxnode]; 18 int sz; 19 ll ans; 20 21 void init(){ 22 memset(v1,0,sizeof(v1)); 23 memset(v2,0,sizeof(v2)); 24 memset(ch,0,sizeof(ch)); 25 head[0]=nex[0]=-1; 26 sz=1; 27 ans=0; 28 } 29 30 void insert_(char* s,int l,int r){ 31 int u=0,v; 32 for(int i=l;i<r;i++){ 33 int ok=0; 34 v1[u]+=flag[0][i]; 35 for(v=head[u];~v;v=nex[v]) if(ch[v]==s[i]){ 36 ok=1; 37 break; 38 } 39 if(!ok){ 40 v=sz++; 41 ch[v]=s[i]; 42 nex[v]=head[u]; 43 head[u]=v; 44 head[v]=-1; 45 } 46 u=v; 47 } 48 v2[u]++; 49 } 50 51 void query(char* s,int l,int r){ 52 int u=0,v; 53 for(int i=l;i<r;i++){ 54 int ok=0; 55 for(v=head[u];~v;v=nex[v]) if(ch[v]==s[i]){ 56 ok=1; 57 u=v; 58 break; 59 } 60 if(!ok) return ; 61 if(v2[u]){ 62 if(i<r-1&&flag[1][i+1]||i==r-1) ans+=v2[u]; 63 } 64 } 65 ans+=v1[u]; 66 } 67 }; 68 69 70 Trie trie; 71 72 void getnex(char* t,int l,int r){ 73 nex[l]=r-l; 74 int a=0,p=0; 75 for(int i=1;i<r-l;i++){ 76 if(i>=p||i+nex[i-a+l]>=p){ 77 if(i>=p) p=i; 78 while(p<r-l&&t[p+l]==t[p-i+l]) p++; 79 nex[i+l]=p-i; 80 a=i; 81 }else nex[i+l]=nex[i-a+l]; 82 } 83 } 84 85 void exkmp(char* s,char* t,int l,int r,int b){ 86 getnex(t,l,r); 87 int a=0,p=0; 88 for(int i=0;i<r-l;i++){ 89 if(i>=p||i+nex[i-a+l]>=p){ 90 if(i>=p) p=i; 91 while(p<r-l&&s[p+l]==t[p-i+l]) p++; 92 ex[i+l]=p-i; 93 a=i; 94 }else ex[i+l]=nex[i-a+l]; 95 } 96 for(int i=l;i<r;i++){ 97 if(i+ex[i]==r) flag[b][i]=1; 98 } 99 } 100 101 int main(){ 102 int n; 103 while(scanf("%d",&n)!=EOF){ 104 trie.init(); 105 memset(flag,0,sizeof(flag)); 106 int L=0; 107 for(int i=0;i<n;i++){ 108 scanf("%d%s",&len,s+L); 109 bg[i]=L;ed[i]=L+len; 110 for(int j=0;j<len;j++) t[j+L]=s[L+len-j-1]; 111 L+=len; 112 exkmp(s,t,bg[i],ed[i],0); 113 exkmp(t,s,bg[i],ed[i],1); 114 trie.insert_(s,bg[i],ed[i]); 115 } 116 for(int i=0;i<n;i++) { 117 trie.query(t,bg[i],ed[i]); 118 } 119 printf("%lld ",trie.ans); 120 } 121 return 0; 122 }