bzoj1524【POI2006】Pal

1524: [POI2006]Pal

Time Limit: 5 Sec   Memory Limit: 357 MB
Submit: 367   Solved: 121
[ Submit][ Status][ Discuss]

Description

给出n个回文串s1, s2, …, sn 求如下二元组(i, j)的个数 si + sj 仍然是回文串 规模 输入串总长不超过2M bytes 

Input

The first line of input file contains the number of strings n. The following n lines describe each string: The i+1-th line contains the length of the i-th string li, then a single space and a string of li small letters of English alphabet. You can assume that the total length of all strings will not exceed 2,000,000. Two strings in different line may be the same. 

Output

Print out only one integer, the number of palindromes

Sample Input

6
2 aa
3 aba
3 aaa
6 abaaba
5 aaaaa
4 abba

Sample Output

14





Trie+哈希随便搞搞就行了。

#SXOI2016之蜜汁错误# 考场上忘记每个串都是回文串,想复杂了,最后只拿了30,剩下70全部TLE。




#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define ull unsigned long long
#define maxn 2000005
#define base 233
using namespace std;
int n,tot=1;
int l[maxn],cnt[maxn],num[maxn],t[maxn][26];
ll ans;
ull ha[maxn],p[maxn];
char ch[maxn];
string s[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main()
{
	p[0]=1;F(i,1,2000000) p[i]=p[i-1]*base;
	n=read();
	F(i,1,n)
	{
		l[i]=read();
		scanf("%s",ch);s[i]=ch; //字符串这样读入更快 
//		cin>>s[i]; //TLE
		int now=1;ull tmp=0;
		F(j,0,l[i]-1)
		{
			int x=s[i][j]-'a';
			if (!t[now][x]) t[now][x]=++tot;
			now=t[now][x];
			tmp=tmp*base+(ull)(x+1);
		}
		cnt[now]++;num[now]=i;ha[i]=tmp;
	}
	F(i,1,n)
	{
		int now=1;
		F(j,0,l[i]-1)
		{
			now=t[now][s[i][j]-'a'];
			if (cnt[now]&&ha[num[now]]*p[l[i]]+ha[i]==ha[i]*p[l[num[now]]]+ha[num[now]]) ans+=cnt[now];
		}
	}
	ans=ans*2-n;
	printf("%lld\n",ans);
	return 0;
}


你可能感兴趣的:(poi,哈希,trie,bzoj)