ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

B - Finding Palindromes (字典树+manacher)

2019-02-16 21:43:50  阅读:224  来源: 互联网

标签:tmp pp Palindromes int manacher 字符串 Finding include 回文


题目链接:https://cn.vjudge.net/contest/283743#problem/B

题目大意:给你n个字符串,然后问你将这位n个字符串任意两两组合,然后问你这所有的n*n种情况中,是回文串的有多少个?

题目大意:学到了一个很骚气的存储多个零散字符串的方法,因为有可能个给你很多零散的字符串,我们可以将这些字符串存储在一个字符串里面,然后再额外加一个数组记录每一个字符串的开始位置和截止位置就好了。 然后是对于这个题,首先说一下判断字符串的方法,对于每一个字符串我们通过manacher算法求出每一个点的最长的回文串,然后在字典树中反序存储这个字符串。

举个例子:aaba和baa,这个时候baa插在aaba后面是可以构成回文串的,在字典树中baa是倒序存储的,所以就能够和aaba的前缀aab相匹配,然后我们在看aab后面的子串是不是回文串,如果是回文串的话,这个两个就能够形成回文串,因为前面部分和后面部分是对称的,并且中间部分也是回文串。

我们对于每一个字符串,

surf[i]记录的是对于当前的字符串,从第i+1个位置开始,能不能构成字符串。

pre[i]数组记录的是对于当前的字符串,从当前字符串的第一个位置开始到第i-1个位置,前缀能不能构成回文串。

val[i]数组记录的是字典树中从第0个位置到i所形成的的字符串的个数。

qian[i]数组记录的是当前节点后面是回文串的数目。

查询的时候,每一次查询当前节点后面是不是回文串,如果是的话就加上这个字符串的个数。如果找到了底部还需要注意后面形成的回文串的个数。

AC代码:

  1 #include<iostream>
  2 #include<stack>
  3 #include<iomanip>
  4 #include<cmath>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<string>
  8 #include<cstring>
  9 using namespace std;
 10 # define ll long long
 11 const int maxn = 2e6+7;
 12 const int maxm= 2e6+100;
 13 char str[maxn],tmp[maxn<<1];
 14 bool pre[maxn],suf[maxn];
 15 int pp[maxn<<1],tot;
 16 int qian[maxn],val[maxn];
 17 int start[maxn];
 18 int ch[maxn][28];
 19 void init()
 20 {
 21     for(int i=0; i<=tot; i++)
 22     {
 23         qian[i]=0,val[i]=0;
 24         for(int j=0; j<28; j++)
 25         {
 26             ch[i][j]=0;
 27         }
 28     }
 29     tot=0;
 30 }
 31 void trie(int t)
 32 {
 33     int p=0;
 34     for(int i=start[t+1]-1; i>=start[t]; i--)
 35     {
 36         int tmp=str[i]-'a';
 37         qian[p]+=pre[i];
 38         if(!ch[p][tmp])
 39             ch[p][tmp]=++tot;
 40             p=ch[p][tmp];
 41     }
 42     val[p]+=1;
 43 }
 44 void manacher(int n)
 45 {
 46     int i,mx=0,len=1,id=0;
 47     tmp[0]='$';
 48     for(i=start[n]; i<start[n+1]; i++)
 49     {
 50         tmp[len++]='#';
 51         tmp[len++]=str[i];
 52         pre[i]=0;
 53         suf[i]=0;
 54     }
 55     tmp[len]='#';
 56     tmp[len+1]=0;
 57     for(int i=2; i<len; i++)
 58     {
 59         pp[i] = 1;
 60         if(pp[id]+id > i)
 61             pp[i] = min(pp[id*2-i], pp[id]+id-i);
 62         while(tmp[ i+pp[i] ] == tmp[ i-pp[i] ])
 63             pp[i]++;
 64         if(pp[id]+id < pp[i]+i)
 65             id = i;
 66         if(pp[i]==i)
 67             pre[start[n]+pp[i]-2]=1;
 68         if(i+pp[i]-1==len)
 69             suf[start[n+1]-pp[i]+1]=1;
 70     }
 71 }
 72 ll query(int t)
 73 {
 74     ll sum=0;
 75     int p=0,i;
 76     for( i=start[t]; i<start[t+1]; i++)
 77     {
 78         int tmp=str[i]-'a';
 79         if(ch[p][tmp]==0)
 80             break;
 81             p=ch[p][tmp];
 82         if(suf[i+1]==1||i+1==start[t+1])
 83             sum+=val[p];
 84     }
 85     if(i==start[t+1])
 86         sum+=qian[p];
 87     return sum;
 88 }
 89 int main()
 90 {
 91     int n;
 92     while(~scanf("%d",&n))
 93     {
 94         init();
 95         int len;
 96         for(int i=1; i<=n; i++)
 97         {
 98             scanf("%d%s",&len,str+start[i]);
 99             start[i+1]=start[i]+len;
100             manacher(i);
101             trie(i);
102         }
103         ll ans=0;
104         for(int i=1; i<=n; i++)
105         {
106             ans+=query(i);
107         }
108         printf("%lld\n",ans);
109     }
110     return 0;
111 }

 

标签:tmp,pp,Palindromes,int,manacher,字符串,Finding,include,回文
来源: https://www.cnblogs.com/letlifestop/p/10389314.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有