ZOJ 3661 Palindromic Substring(回文树)

Palindromic Substring


Time Limit: 10 Seconds      Memory Limit: 65536 KB



In the kingdom of string, people like palindromic strings very much. They like only palindromic strings and dislike all other strings. There is a unified formula to calculate the score
of a palindromic string. The score is calculated by applying the following three steps.

  1. Since a palindromic string is symmetric, the second half(excluding the middle of the string if the length is odd) is got rid of, and only the rest is considered. For example, "abba" becomes "ab", "aba" becomes "ab" and "abacaba" becomes "abac".
  2. Define some integer values for ‘a‘ to ‘z‘.
  3. Treat the rest part as a 26-based number M and the score is M modulo 777,777,777.

However different person may have different values for ‘a‘ to ‘z‘. For example, if ‘a‘ is defined as 3, ‘b‘ is defined as 1 and c is defined as 4, then the string "accbcca" has the score
(3×263+4×262+4×26+1) modulo 777777777=55537.

One day, a very long string S is discovered and everyone in the kingdom wants to know that among all the palindromic substrings of S, what the one with the K-th
smallest score is.

Input

The first line contains an integer T(1 ≤ T ≤ 20), the number of test cases.

The first line in each case contains two integers n, m(1 ≤ n ≤ 100000, 1 ≤ m ≤ 20) where n is the length of S and m is
the number of people in the kingdom. The second line is the string S consisting of only lowercase letters. The next m lines each containing 27 integers describes a person in the following format.

Ki va vb ... vz

where va is the value of ‘a‘ for the person, vb is the value of ‘b‘ and so on. It is ensured that the Ki-th smallest palindromic substring
exists and va, vb, ..., vz are in the range of [0, 26). But the values may coincide.

Output

For each person, output the score of the K-th smallest palindromic substring in one line. Print a blank line after each case.

Sample Input

3
6 2
abcdca
3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
7 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
4 10
zzzz
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
9 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
10 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14
51 4
abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba
1 1 3 3 25 20 25 21 7 0 9 7 3 16 15 14 19 5 19 19 19 22 8 23 2 4 1
25 1 3 3 25 20 25 21 7 0 9 7 3 16 15 14 19 5 19 19 19 22 8 23 2 4 1
26 1 3 3 25 20 25 21 7 0 9 7 3 16 15 14 19 5 19 19 19 22 8 23 2 4 1
76 1 3 3 25 20 25 21 7 0 9 7 3 16 15 14 19 5 19 19 19 22 8 23 2 4 1

Sample Output

1
620

14
14
14
14
14
14
14
378
378
378

0
9
14

733665286

回文树
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;
typedef long long int LL;
const int maxn=1e5+5;
const int mod=777777777;
char str[maxn];
int n,m;
LL k;
int a[26];
LL pow(int x)
{
	LL sum=1;
	LL n=26;
	for(x;x;x>>=1)
	{
		if(x&1)
			sum=(sum*n)%mod;
		n=(n*n)%mod;
	}
	return sum;
}
struct Node
{
	LL num;
	LL sum;
}c[maxn];
int cmp(Node a,Node b)
{
	return a.sum<b.sum;
}
struct Tree
{
	int next[maxn][26];
	int fail[maxn];
	LL num[maxn];
	int cnt[maxn];
	int len[maxn];
	int s[maxn];
	int last,p,n;
	int new_node(int x)
	{
		memset(next[p],0,sizeof(next[p]));
		cnt[p]=0;
		num[p]=0;
		len[p]=x;
		return p++;
	}
	void init()
	{
		p=0;
		new_node(0);
		new_node(-1);
		last=0;
		n=0;
		s[0]=-1;
		fail[0]=1;
	}
	int get_fail(int x)
	{
		while(s[n-len[x]-1]!=s[n])
			x=fail[x];
		return x;
	}
	int add(int x)
	{
		x-='a';
		s[++n]=x;
		int cur=get_fail(last);
		if(!(last=next[cur][x]))
		{
			int now=new_node(len[cur]+2);
			fail[now]=next[get_fail(fail[cur])][x];
			next[cur][x]=now;
			num[now]=(num[cur]+((LL)pow((len[cur]+1)/2)*a[x])%mod)%mod;
			last=now;
		}
		cnt[last]++;
		return 1;
	}
	void count()
	{
		for(int i=p-1;i>=0;i--)
			cnt[fail[i]]+=cnt[i];
	}
	void fun()
	{
		count();
		int cot=0;
		for(int i=2;i<p;i++)
		{
			c[cot].num=cnt[i];
			c[cot++].sum=num[i];
		}
		sort(c,c+cot,cmp);
		int i;
		for( i=0;i<cot;i++)
		{
			if(k>c[i].num)
			{
				k-=c[i].num;
			}
			else
				break;
		}
        printf("%d\n",c[i].sum);
	}
}tree;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
        scanf("%d%d",&n,&m);
		scanf("%s",str);
		for(int i=1;i<=m;i++)
		{
			scanf("%lld",&k);
			for(int j=0;j<26;j++)
				scanf("%d",&a[j]);
			tree.init();
			for(int j=0;j<n;j++)
			{
                 tree.add(str[j]);
			}
			tree.fun();
        }
		cout<<endl;
	}
	return 0;
}

时间: 2024-11-09 04:43:21

ZOJ 3661 Palindromic Substring(回文树)的相关文章

HDU 5658 CA Loves Palindromic(回文树)

CA Loves Palindromic Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 301    Accepted Submission(s): 131 Problem Description CA loves strings, especially loves the palindrome strings. One day

Palindromic Tree 回文自动机-回文树 例题+讲解

---恢复内容开始--- 回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同回文串包含的本质不同回文串种类 (本文参考自Palindromic Tree——回文树[处理一类回文串问题的强力工具],Palindromic Tree 回文自动机-回文树 解决回文串的神器) 下面介绍一些数组的意义 next[][]类似于字典树,指向当前字符串在两段同时加

hdu5658 CA Loves Palindromic 回文树

回文树在处理回文方面真的比manacher要好用得多... #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; t

HDU 5157 Harry and magic string(回文树)

Harry and magic string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 223    Accepted Submission(s): 110 Problem Description Harry got a string T, he wanted to know the number of T's disjoint

CF245H Queries for Number of Palindromes(回文树)

题意翻译 题目描述 给你一个字符串s由小写字母组成,有q组询问,每组询问给你两个数,l和r,问在字符串区间l到r的字串中,包含多少回文串. 输入格式 第1行,给出s,s的长度小于5000 第2行给出q(1<=q<=10^6) 第2至2+q行 给出每组询问的l和r 输出格式 输出每组询问所问的数量. 题目描述 You've got a string s=\(s_{1}\)\(s_{2}\)...\(s_{|s|}\) of length |s| , consisting of lowercase

回文树

(没有坑怎么填?) 最近膜了一些关于回文串的题目,感到非常有意思,遂开篇记录. 在逛UOJ的题目时发现了vfk添上了新题,APIO 2014的题目.本身是一件很正常的事,而它事实上也没有变成什么了不得的事.我看到了Palindrome这个标题---回文串已经烂大街了,没什么新意.不过我很早就向学习回文树这东西了,久仰其大名而未尝真正去了结果它,于是我就顺手撸了一把豪哥的论文,发现他讲解的实在是晦涩难懂---论文的通病,就是虽然表述没有歧义,但是难以理解.嘛,然后我就找了几个标程,发现回文树这东西

回文树或者回文自动机,及相关例题

回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数) 基本建立思路是先建立其前缀的回文树,然后每加上一个字符,统计影响: 回文树存在fail指针但一般不承接字符串匹配问题: (回文树大概可以判定一个回文串是不是一个串的子串,但KMP之类的可以做得更好) 构建好的回文树,是这样的: (好难看) 可看出: 存在两个树结构,分别记录奇数|偶数长度的回文:

bzoj3676: [Apio2014]回文串 回文树

回文树的裸题. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=500100; const int INF=1e9+10; struct PalinTree { int ch[maxn][26],f[maxn]; int

HDU3948 &amp; 回文树模板

Description: 求本质不同回文子串的个数 Solution: 回文树模板,学一学贴一贴啊... Code: /*================================= # Created time: 2016-04-20 20:55 # Filename: hdu3948.cpp # Description: =================================*/ #define me AcrossTheSky&HalfSummer11 #include &l