• Finding Palindromes POJ


    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
    ",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
    ",trie.ans);
    120     }
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    Caliburn.Micro代码示例
    HtmlAgilityPack解析全国区号页面到XML
    MySql避免全表扫描【转】
    jdk和tomcat环境部署
    FusionCharts ajax 调用方式
    Could not find artifact com.sun:tools:jar:1.5.0
    winform开发中绑定combox到枚举
    TextBoxButton控件的开发实现
    SendMessage函数的常用消息及其应用大全
    SqlServer2008快照隔离模式的业务应用
  • 原文地址:https://www.cnblogs.com/yijiull/p/7412559.html
Copyright © 2020-2023  润新知