Finding Palindromes POJ - 3376(Trie树&&扩展KMP)

Finding Palindromes

 POJ - 3376

题意:给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\n",ans);
95     }
96     return 0;
97 }
View Code

 

补上用前向星存边的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\n",trie.ans);
120     }
121     return 0;
122 }
View Code

 

posted @ 2017-08-22 17:11  yijiull  阅读(179)  评论(0编辑  收藏  举报