poj 3376 Finding Palindromes

Finding Palindromes

http://poj.org/problem?id=3376

Time Limit: 10000MS   Memory Limit: 262144K
     
Case Time Limit: 2000MS

Description

A word is called a palindrome if we read from right to left is as same as we read from left to right. For example, "dad", "eye" and "racecar" are all palindromes, but "odd", "see" and "orange" are not palindromes.

Given n strings, you can generate n × n pairs of them and concatenate the pairs into single words. The task is to count how many of the so generated words are palindromes.

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

3
1 a
2 ab
2 ba

Sample Output

5

Hint

The 5 palindromes are: 
aa aba aba abba baab

建立trie树

用原串的反串在trie树上匹配

假设反串匹配到i,trie树上到j

1、如果j是单词节点,即以j结尾的单词是反串的前缀,那么如果i以后(反串剩余的部分,不包括i)是回文串,以j结尾的单词都可以与匹配的单词构成回文串

2、如果反串匹配完了,即反串是以i结尾的单词的前缀,那么j后面(不包括j)有多少回文串,就可以产生多少合法答案

关键:字符串的前缀回文和后缀回文

用扩展kmp

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2000008
using namespace std;
bool f[2][N];
long long ans;
char T[N],S[N];
int len,tot,root,id;
int st[N],ed[N],cnt;
int nxt[N],expand[N];
int trie[N][26],mark[N],sum[N];
void getnxt(char *s,int ll,int rr)
{
    int a=ll;
    nxt[0]=rr-ll+1;
    while(a+1<=rr && s[a]==s[a+1]) a++;
    nxt[1]=a-ll;
    a=1+ll;
    int p,l,j;
    for(int k=2+ll;k<=rr;k++)
    {
        p=a-ll+nxt[a-ll]-1; l=nxt[k-a];
        if(k-ll+l-1>=p)
        {
            j=p-k+ll+1>0 ? p-k+ll+1 : 0;
            while(k+j<=rr && s[k+j]==s[j+ll]) j++;
            nxt[k-ll]=j;
            a=k;
        }
        else nxt[k-ll]=l;
    }
}
void exkmp(char *s,char *t,int ll,int rr,int w)
{
    getnxt(t,ll,rr);
    int a=ll;
    while(a<=rr && s[a]==t[a]) a++;
    expand[0]=a-ll;
    a=ll;
    int p,l,j;
    for(int k=ll+1;k<=rr;k++)
    {
        p=a-ll+expand[a-ll]-1; l=nxt[k-a];
        if(k-ll+l-1>=p)
        {
            j=p-k+ll+1>0 ? p-k+ll+1 : 0;
            while(k+j<=rr && s[k+j]==t[j+ll]) j++;
            expand[k-ll]=j;
            a=k;
        }
        else expand[k-ll]=l;
    }
    for(int i=ll-ll;i<=rr-ll;i++)
     if(i+expand[i]==rr-ll+1) f[w][i+ll]=true;
}
void insert(int ll,int rr)
{
    root=0;
    for(int i=ll;i<=rr;i++)
    {
        id=S[i]-‘a‘;
        sum[root]+=f[0][i];
        if(!trie[root][id]) trie[root][id]=++tot;
        root=trie[root][id];
    }
    mark[root]++;
}
void find(int ll,int rr)
{
    root=0;
    for(int i=ll;i<=rr;i++)
    {
        id=T[i]-‘a‘;
        root=trie[root][id];
        if(!root) return;
        if(i!=rr&&f[1][i+1] || i==rr) ans+=mark[root];
    }
     ans+=sum[root];
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%s",&len,S+cnt);
        for(int j=0;j<len;j++) T[cnt+j]=S[cnt+len-j-1];
        st[i]=cnt;
        ed[i]=cnt+len-1;
        exkmp(S,T,st[i],ed[i],0);
        exkmp(T,S,st[i],ed[i],1);
        cnt+=len;
        insert(st[i],ed[i]);
    }
    for(int i=1;i<=n;i++)
     find(st[i],ed[i]);
    printf("%lld\n",ans);
}
时间: 2024-12-14 23:28:19

poj 3376 Finding Palindromes的相关文章

POJ 2049 Finding Nemo 优先队列 STL

题目链接:http://poj.org/problem?id=2049 题目利用了<海底总动员>的情节,小丑鱼尼莫迷路了,他老爸去营救他便是题意. 题目给出了这样的地图,说是假设地图由墙和门组成,忽略墙的厚度,地图上有门,没有墙的地方是可以自由行动的问可以经过最少多少道门便可以营救到尼莫. 这个题给的数据是墙的交点为整数点,但鱼爸爸实在非墙的地方自由移动. 因此,这个题有两个难点: 1.如果建图保存地图 2.如何在地图上遍历 由于题目是给出一个点(x,y),来表示一段墙 我便用一对X,Y来表示

POJ 2049— Finding Nemo(三维BFS)10/200

海底总动员.... 这个题开始不会建图,彻底颠覆以前我对广搜题的想法.想了好久, 忽然想到省赛时HYPO让我做三维BFS来着,一直没做,看到POJ计划这个题,就是三维BFS解题,就做了一下, 对于这个题....实在不知道说什么好,又坑.又SB,POJ的后台数据和题目描述的完全不一样,看了DIscuss之后开始 改动代码,最后改的又臭又长,搜了无数题解找数据,卡了整整两天. 挥挥洒洒 160行....同时也是我第一次使用  三维建图+BFS,纪念一下! 2049 算是我攻克POJ计划的第一个卡两天

POJ 2049 Finding Nemo BFS

题目大意:给你一个奇奇怪怪的迷宫, 这个迷宫包括墙和门.再给你一个起始坐标, 问你从迷宫内到外面至少要穿越多少的门. 题目分析: 穿越多少门等同于路过了多少个格子. 为此我们可以将整个地图中的格子,门,墙,墙的交界处(格子的顶点)全部抽象成点. 即坐标(奇数,奇数)为格子的坐标,坐标(奇数,偶数)或坐标(偶数,奇数)为门或墙的坐标,坐标(偶数,偶数)为格子的顶点. 这样题目就转化成了从起始点所在的格子走到迷宫外的格子最少要经过多少个格子,用step[i][j]表示走出迷宫后遇到的第一个格子的坐标

POJ 2049 Finding Nemo

Finding Nemo Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 8631   Accepted: 2019 Description Nemo is a naughty boy. One day he went into the deep sea all by himself. Unfortunately, he became lost and couldn't find his way home. Therefo

POJ 3175 Finding Bovine Roots(思路)

题目地址:http://poj.org/problem?id=3175 思路: 若x.123....这个数字的平方是一个整数的话,那必然,sqr(x.124)>ceil(sqr(x.123))[ceil向上取整].所以,可以从小到大枚举它的整数部分x,遇到的第一个满足结果的x,即为答案. #include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<a

poj 3681 Finding the Rectangle 尺取法解最小矩形覆盖问题

题意: 平面上有n个点,现在要求一个面积最小的矩形能完全覆盖其中的m个点(边界不算). 分析: 求满足某个性质的最小区间的问题尺取法比二分还要高效,这题可以在x上暴力枚举,在y上用尺取法(在x,y上都用尺取法是不对的). 代码: //poj 3681 //sep9 #include <iostream> #include <algorithm> using namespace std; int n,m,ans; struct P { int x,y; }pnt1[256],pnt2

[转] POJ字符串分类

POJ 1002 - 487-3279(基础)http://acm.pku.edu.cn/JudgeOnline/problem?id=1002题意:略解法:二叉查找数,map,快排... POJ 1200 - Crazy Search(基础)http://acm.pku.edu.cn/JudgeOnline/problem?id=1200题意:找出不相同的子串数量,字母表大小和子串长度会给定,这题很推荐hash入门者一做解法:hash(建议karp-rabin) POJ 1204 - Word

poj3376 KMP+字典树求回文串数量(n*n)

Finding Palindromes Time Limit: 10000MS   Memory Limit: 262144K Total Submissions: 4043   Accepted: 746 Case Time Limit: 2000MS Description A word is called a palindrome if we read from right to left is as same as we read from left to right. For exam

leetcode-longest palindromic substring-by 1337c0d3r

Given a string S, find the longest palindromic substring in S. Note:This is Part II of the article: Longest Palindromic Substring. Here, we describe an algorithm (Manacher’s algorithm) which finds the longest palindromic substring in linear time. Ple