• POJ 3376 Finding Palindromes(manacher求前后缀回文串+trie)


    题目链接:http://poj.org/problem?id=3376

    题目大意:给你n个字符串,这n个字符串可以两两组合形成n*n个字符串,求这些字符串中有几个是回文串。

    解题思路:思路参考了这里:http://blog.csdn.net/qq_30241305/article/details/50718051

    做法:首先由两个字符串A,B.要使它们能组成回文串有三种情况

    情况① :alen < blen

        abc  abacba  abcaba   

         A               B    RB

    如上所示,A是B的反串前缀,且b的剩余部分可以认为是后缀是回文串

    情况②:alen > blen

      abcaba  cba  abc

       A    B   RB

    B的反串是A的前缀,且a的后缀是回文串

    情况③:alen == blen

    b是a的反串,这个就不用解释了吧。

    现将所有正序字符(原字符串)串建立在字典树中。然后用反串去匹配,根据上面给出的三种情况作出判断。

    另外:因为只给了字符串的总长度,所以,只开一维的字符串数组,每次接着上次字符串结束的位置开始即可。为了方便,记录字符串开始的位置,和结束的位置。

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 typedef long long LL;
      7 const int N=2e6+5;
      8 
      9 LL ans;
     10 int n,len1,len2,idx,root;
     11 char s[N],str[N*2];
     12 int trie[N][27],p[N*2],End[N],hou[N];//End[i]表示以节点i为结尾的字符串的数目
     13                                      //hou[i]表示节点i之后(不包括i)的后缀回文串数目
     14 
     15 struct node{
     16     int st,len;
     17 }a[N];
     18 
     19 void init(){
     20     str[0]='$';
     21     str[1]='#';
     22     len1--;
     23     for(int i=1;i<=len1;i++){
     24         str[i*2]=s[i];
     25         str[i*2+1]='#';
     26     }
     27     len2=len1*2+2;
     28     str[len2]='@';
     29 }
     30 
     31 void manacher(){
     32     init();
     33     int id=-1,mx=-1;
     34     for(int i=1;i<len2;i++){
     35         if(mx>i) p[i]=min(p[id*2-i],mx-i);
     36         else p[i]=1;
     37         while(str[i-p[i]]==str[i+p[i]])
     38             p[i]++;
     39         if(i+p[i]>mx){
     40             mx=i+p[i];
     41             id=i;
     42         }
     43     }
     44 }
     45 
     46 //将字符串正序插入字典树中
     47 void Insert(){
     48     for(int i=0;i<n;i++){
     49         int now=root;
     50         for(int j=a[i].st;j<a[i].st+a[i].len;j++){
     51             if(!trie[now][s[j]-'a']) trie[now][s[j]-'a']=++idx;
     52             now=trie[now][s[j]-'a'];
     53             int mid=((j+1)*2-1+(a[i].st+a[i].len-1)*2+1)/2;//(j+1)*2是s[j+1]对应str的位置(j+1)*2-1则是边缘的'#',同理(a[i].st+a[i].len-1)*2+1也对应边缘'#'
     54             if(p[mid]>mid-(j+1)*2+1)
     55                 hou[now]++;
     56         }
     57         hou[now]--;                                        //因为字符串末尾的"#"也算成一个回文串了,所以要减掉
     58         End[now]++;
     59     }
     60 }
     61 
     62 //计算可以生成的回文串数
     63 void Find(){
     64     for(int i=0;i<n;i++){
     65         int now=root;
     66         for(int j=a[i].st+a[i].len-1;j>=a[i].st;j--){
     67             //匹配失败,没有对应的字符串
     68             if(!trie[now][s[j]-'a']){
     69                 now=-1;
     70                 break;
     71             }
     72             now=trie[now][s[j]-'a'];
     73             if(End[now]){                                   //情况①或③
     74                 int mid=(a[i].st*2-1+(j-1)*2+1)/2;
     75                 if(p[mid]>mid-a[i].st*2+1)
     76                     ans+=End[now];
     77             }
     78         }
     79         if(now!=-1) ans+=hou[now];                          //情况②
     80     }
     81 }
     82 
     83 int main(){
     84     while(~scanf("%d",&n)){
     85         idx=0,len1=1,ans=0;
     86         memset(trie,0,sizeof(trie));
     87         memset(End,0,sizeof(End));
     88         memset(hou,0,sizeof(hou));
     89         for(int i=0;i<n;i++){
     90             scanf("%d",&a[i].len);
     91             scanf("%s",s+len1);
     92             a[i].st=len1;
     93             len1+=a[i].len;
     94         }
     95         manacher();
     96         Insert();
     97         Find();
     98         printf("%lld
    ",ans);
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    HTTP/HLS/RTMP超级负载测试工具(转)
    Jmeter监控Linux服务器性能
    装饰器做缓存
    内置装饰器
    Python装饰器 计时器记录方法执行性能
    【Python】装饰器实现日志记录
    Java对关于两个地点的根据经纬度算出后排序
    JS获得当前位置信息
    百度地图插件开发使用三 及jquery function(a.b)排序等
    css用clearfix清除浮动
  • 原文地址:https://www.cnblogs.com/fu3638/p/8503514.html
Copyright © 2020-2023  润新知