ural 1960 Palindromes and Super Abilities

题意:找出s[1..x]的本质不同的回文串的个数

分析:回文树模板题

/************************************************
Author        :DarkTong
Created Time  :2016年09月21日 星期三 21时17分07秒
File Name     :a.cpp
 *************************************************/

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const int maxn = 100000 + 10;
const int N = 26;

struct Palindromic_Tree
{
	int next[maxn][N];
	int fail[maxn];
	int cnt[maxn];
	int num[maxn];
	int len[maxn];
	int S[maxn];
	int last;
	int n;
	int p;
	int ans[maxn];

	int newNode(int l)
	{
		for(int i=0;i<N;++i) next[p][i]=0;
		cnt[p] = 0;
		num[p] = 0;
		len[p] = l;
		return p ++;
	}

	void init()
	{
		p = 0;
		newNode(0);
		newNode(-1);
		last = 0;
		n = 0;
		S[n] = -1;
		fail[0] = 1;

		ans[0] = 0;
	}

	int get_fail(int x)
	{
		while(S[n - len[x] - 1] != S[n]) x = fail[x];
		return x;
	}

	void add(int c)
	{
		c -= ‘a‘;
		S[++ n] = c;
		int cur = get_fail(last);
		if(!next[cur][c])
		{
			int now = newNode(len[cur] + 2);
			fail[now] = next[get_fail(fail[cur])][c];
			next[cur][c] = now;
			num[now] = num[fail[now]] + 1;
			ans[n] = ans[n-1] + 1;
		}
		else ans[n] = ans[n-1];
		last = next[cur][c];
		cnt[last] ++;
	}

	void count()
	{
		for(int i=p-1;i>=0;--i) cnt[fail[i]] += cnt[i];
	}

	void solve(char *s)
	{
		int cur = 0;
		int n = strlen(s+1);
		for(int i=1; i<=n ; ++i)
		{
			cur = next[cur][s[i]-‘a‘];
			printf("%d%c", cnt[i], i==n ? ‘\n‘ : ‘ ‘);
		}
	}
}plt;
char s[maxn];

int main()
{
	int T, cas=1;
	scanf("%s", s+1);
	plt.init();
	for(int i=1; s[i] ; ++ i)
		plt.add(s[i]);
	//	plt.count();
	//	plt.solve(s);
	int n = strlen(s+1);
	for(int i=1;i<=n;++i) printf("%d%c", plt.ans[i], i==n ? ‘\n‘ : ‘ ‘);

	return 0;
}

  

时间: 2024-11-10 12:01:31

ural 1960 Palindromes and Super Abilities的相关文章

ural 1960 Palindromes and Super Abilities 题解

题意:给一个串s,按顺序一个个加入到序列里面.输出每次加入之后序列中的本质不同的回文串个数. 回文自动机模板题- -extend函数里面,如果那个if进去了,就代表多了一个本质不同的回文串. 1 #include<cstdio> 2 #include<cstring> 3 const int MAXN=100000+5; 4 const int SIGMA_SIZE=26; 5 struct Node{ 6 int num,len; 7 Node* go[SIGMA_SIZE],*

URAL 2040 Palindromes and Super Abilities 2(回文树)

Palindromes and Super Abilities 2 Time Limit: 1MS   Memory Limit: 102400KB   64bit IO Format: %I64d & %I64u Status Description Dima adds letters s1, -, sn one by one to the end of a word. After each letter, he asks Misha to tell him how many new pali

Ural 2040 Palindromes and Super Abilities 2

题目太坑,发一波纪念一下 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=5000010; 5 struct PAM{ 6 int cnt,last; 7 int a[N][2],l[N],f[N]; 8 char s[N]; 9 PAM(){ 10 cnt=f[0]=f[1]=1; 11 l[1]=-1; 12 } 13 int get_fail(int x,int

URAL 2040 (回文自动机)

Problem Palindromes and Super Abilities 2 题目大意 解题分析 参考程序 1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <string> 8 #include <vector>

回文自动机入门题

URAL-1960.Palindromes and Super Abilities 传送门 •题意 给你一个长度为 n 的字符串 s,下标从 1 开始: 输出 n 个数,第 i 个数表示 1~i 内有多少个本质不同的回文串: •题解 回文自动机入门题: 定义 ans[ i ] 表示 1~i 共有 $ans_{i}$ 个本质不同的回文串: $ans_{i}=ans_{i-1}$+{第 i 个字符可形成本质不同的回文串 ? 1:0}; •Code 1 #include<bits/stdc++.h>

Petrozavodsk Winter-2013. Ural FU Contest Problem D. Five Palindromes manacher、一个串切割成5个回文子串、优化

Ural Federal University Contest, SKB Kontur Cup Petrozavodsk Winter Training Camp, Saturday, February 2, 2013 Problem D. Five Palindromes Input file: input.txt Output file: output.txt Time limit: 2 seconds (3 seconds for Java) Memory limit: 256 mebib

回文串+回溯法 URAL 1635 Mnemonics and Palindromes

题目传送门 1 /* 2 题意:给出一个长为n的仅由小写英文字母组成的字符串,求它的回文串划分的元素的最小个数,并按顺序输出此划分方案 3 回文串+回溯:dp[i] 表示前i+1个字符(从0开始)最少需要划分的数量,最大值是i+1,即单个回文串: 4 之前设置ok[j][j+i] 判断从j到j+i的字符是否为回文串(注意两个for的顺序,为满足ok[j][j+i] = ok[j+1][j+i-1]) 5 最后枚举找到最优划分点,用pre[i]记录前一个位置,print函数 输出空格 6 */ 7

Ural 1635 Mnemonics and Palindromes(DP)

题目地址:Ural 1635 又是输出路径的DP...连着做了好多个了.. 状态转移还是挺简单的.要先预处理出来所有的回文串,tag[i][j]为1表示字符串i--j是一个回文串,否则不是回文串.预处理时要用n^2的方法,即枚举回文串中间,可以分奇数和偶数两种分别求一次. 然后dp转移方程为,若tag[j][i]==1,dp[i]=min(dp[i],dp[j-1]+1); 对于最令人讨厌的路径输出,可以用pre来记录回文串前驱分裂点,然后根据这些分裂点来输出. 代码如下: #include <

ural Mnemonics and Palindromes (dp)

http://acm.timus.ru/problem.aspx?space=1&num=1635 给出一个字符串,将这个字符串分成尽量少的回文串. 起初没有思路,想着应该先预处理出所有的回文串,然后进行dp.但是字符串的长度是4000,O(n^3)肯定不行,其实可以转化为O(n^2),就是枚举中点而不是枚举起点和终点,又NC了吧. 然后就是线性的dp了.dp[i]表示到第i位为止最少的回文串数,那么dp[i] = min(dp[i],dp[j+1]+1),j < i 且i到j也是回文串.