Up Sky,Mr.Zhu
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 46 Accepted Submission(s): 14
Problem Description Given a string S[0,…n-1],and the length of each palindrome substring in S is less than 20.
Define special string of a palindrome string STR[0,…,n-1] is STR[floor(n/2),…,n-1]
Given L,R and a string T, Query the number of palindrome strings, whose the prefix of special string is T, in S[L,…,R]
ps:floor means the function in C++ language
(No relation between statement and title)
Input There are severval cases,please peocess until EOF.
The first line contains string S.(1<=|S|<=1e5)
The second line is a number q means the number of querys.(1<=q<=1e5)
The next q lines,each line contains two numbers L,R and a string T.(1<=L<=R<=|S|,1<=|T|<=10)
All strings only contain ‘a’,’b’,’c’,’d’ and ‘e’.
Output For each query,you should output the number of palindrome strings which satisfied previous condition in a line.
Sample Input
bceaeedde 5 5 8 e 3 5 e 1 2 a 5 9 d 5 9 de
Sample Output
3 2 0 4 1
Author UESTC
Source
2016 Multi-University Training Contest 6
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5801
题目大意:
定义一个回文串的特征串为其从中心到结尾的部分,给出一个字符串S,q次询问,每次询问以一个字符串t为特征串前缀落在区间L到R之间的回文串数量,S中回文串长度不会超过20。
解题思路:
先Manacher预处理,然后我们用Trie树来维护以每个位置为起始的特征串,注意到特征串的长度不会超过10,所以我们可以每次按一个长度建立可持久化Trie树,每次对所有询问的区间在线查询,更新答案,做10次即可。
为了不去考虑角码的运算,我将奇偶串分开讨论了,代码就显得有些冗余。最后要吐槽hdu谜一样的java内存机制,开始估计数组最大要开到10^6,结果MLE了,索性开到10^5枚举内存,居然神奇的AC了。
AC代码:
import java.io.*;
import java.util.*;
public class Main {
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static int nextInt() throws IOException
{
in.nextToken();
return (int)in.nval;
}
static String next() throws IOException
{
in.nextToken();
return in.sval;
}
static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
static int n,m,len,sz,a;
static char[] s;
static char[] ss=new char[200005];
static int[] pp=new int[200005];
static int[] aa=new int[100005];
static int[] bb=new int[100005];
static int[] cc=new int[100005];
static int[] rt=new int[100005];
static int[] ans=new int[100005];
static int[] cnt=new int[100005];
static char[][] tt=new char[100005][];
static int[][] ch=new int[100005][5];
static void Manacher()
{
Arrays.fill(ss,'#');
for(int i=0;i<n;i++)
ss[i*2+2]=s[i];
len=n*2+1;ss[0]='$';
int max=0,id=0;
for(int i=1;i<=len;i++)
{
if(max>i)
pp[i]=Math.min(pp[id*2-i],max-i);
else pp[i]=1;
while(ss[i+pp[i]]==ss[i-pp[i]])
pp[i]++;
if(i+pp[i]>max) { max=i+pp[i];id=i;}
}
}
static void insert(int a,int b,int l,int r)
{
int u=a,v=b,p;
for(int i=l;i<=r;i++)
{
p=ss[i]-'a';
for(int k=0;k<5;k++)
ch[u][k]=ch[v][k];
cnt[u]=cnt[v]+1;
ch[u][p]=++sz;
u=ch[u][p];v=ch[v][p];
}
cnt[u]=cnt[v]+1;
}
static int query(int a,int b,int k)
{
int u=a,v=b,p;
for(int i=0;i<tt[k].length;i++)
{
p=tt[k][i]-'a';
u=ch[u][p];v=ch[v][p];
}
return cnt[v]-cnt[u];
}
public static void main(String[] args) throws IOException {
//Scanner in=new Scanner(System.in);
while(in.nextToken()!=StreamTokenizer.TT_EOF)
{
s=in.sval.toCharArray();
n=s.length;
Manacher();
for(int i=n;i>0;i--) ss[i]=s[i-1];
m=nextInt();
for(int i=1;i<=m;i++)
{
aa[i]=nextInt();bb[i]=nextInt();
tt[i]=next().toCharArray();
cc[i]=tt[i].length;
}
for(int i=1;i<=m;i++) ans[i]=0;
for(int k=1;k<=10;k++)
{
sz=0;rt[0]=++sz;
for(int i=1;i<=n;i++)
{
a=pp[i*2]/2;
if(a>=k)
{
rt[i]=++sz;
insert(rt[i],rt[i-1],i,i+k-1);
}
else rt[i]=rt[i-1];
}
for(int i=1;i<=m;i++)
{
if(cc[i]>k||k*2-1>bb[i]-aa[i]+1) continue;
ans[i]+=query(rt[aa[i]+k-2],rt[bb[i]-k+1],i);
}
sz=0;rt[0]=++sz;
for(int i=1;i<=n;i++)
{
a=pp[i*2-1]/2;
if(a>=k)
{
rt[i]=++sz;
insert(rt[i],rt[i-1],i,i+k-1);
}
else rt[i]=rt[i-1];
}
for(int i=1;i<=m;i++)
{
if(cc[i]>k||k*2>bb[i]-aa[i]+1) continue;
ans[i]+=query(rt[aa[i]+k-1],rt[bb[i]-k+1],i);
}
}
for(int i=1;i<=m;i++)
out.println(ans[i]);
}
out.flush();
}
}