HYSBZ - 2160 cheerleading rehearsal (palindrome automaton)

Keywords: iOS

Title Link: Click to view

In this paper, we give a string s and an integer k. now we need to find the product of the length of all the palindrome substrings whose length is an odd number from the largest to the smallest

Problem analysis: after the palindrome automaton runs the string s once, it will take out the length and occurrence times of the nodes whose length is odd, and cooperate with the fast power traversal to find the answer once

Code:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;
 
const int N=1e6+100;

const int mod=19930726;
 
char s[N];
 
int n;
 
struct Palindrome_tree
{
    int nxt[N][26];
    int fail[N]; // Node with the longest palindrome suffix of the current node
    int len[N]; // Length of palindrome string represented by current node
    int cnt[N]; // The number of palindrome strings of the current node can be obtained after getcnt
    int sed[N]; // The number of palindrome strings suffixed with the current node (it is not the number of types of palindrome strings at the end of i, if the number of palindrome strings at the end of each point is required, last is used)
    int record[N]; //record records the ending position of the node palindrome string
    char s[N];
    int tot; // Node number
    int last; // Previous node
    int n;//The length of the current string 
    void init()
    {
        tot = n = 0;
        memset(fail, 0, sizeof fail);
        memset(cnt, 0, sizeof cnt);
        memset(sed, 0, sizeof sed);
        memset(len, 0, sizeof len);
        memset(nxt, 0, sizeof nxt);
    }
    void build()
    {
        len[0] = 0, len[1] = -1; // 0 is even length root, 1 is odd length root
        tot = 1, last = 0;
        fail[0] = 1;
    }
    int getfail(int x, int n)
    {
        while (s[n - len[x] - 1] != s[n]||n-len[x]-1<0) // Compare whether the two ends of the new palindrome string of the x node are equal
        //N-len [x] - 1 < 0 this is my own addition. The first condition is not enough when there are multiple groups, so please delete it manually if there is any error
            x = fail[x]; // If different, then compare both ends of the palindrome string with x suffix
        return x;
    }
    void insert(char ch)
    {
        int c = ch - 'a';//Use a in all lowercase and a in all uppercase, otherwise it will be wrong
        s[++n]=ch;
        int p = getfail(last, n);// Get the node to which the i-th character can be added to form a palindrome string
        if (!nxt[p][c])
        {
            tot++;
            len[tot] = len[p] + 2;  // Add two characters at both ends of the p node
            fail[tot] = nxt[getfail(fail[p], n)][c]; //The suffix palindrome of tot point can be obtained by the suffix palindrome of the previous node
            sed[tot] = sed[fail[tot]] + 1; // The number of palindrome strings ending on the current node
            nxt[p][c] = tot; // New node
        }
        last = nxt[p][c]; // Current node becomes previous node
        cnt[last]++; //Current node palindrome string++
        record[last] = n;
    }
    void get_cnt()
    {
        for (int i = tot; i > 0; i--)
            cnt[fail[i]] += cnt[i];
        //The node of fail[i] is the suffix palindrome string of node i, so the number is added
    }
}tree;

LL q_pow(LL a,LL b)
{
	LL ans=1;
	while(b)
	{
		if(b&1)
			ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}

struct Node
{
	int cnt,len;
	Node(int l,int c)
	{
		len=l;
		cnt=c;
	}
	bool operator<(const Node& a)const
	{
		return len>a.len;
	}
};

vector<Node>node;

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	LL k;
	scanf("%d%lld",&n,&k);
	scanf("%s",s);
	tree.init();
	tree.build();
	for(int i=0;i<n;i++)
		tree.insert(s[i]);
	tree.get_cnt();
	for(int i=2;i<=tree.tot;i++)
		if(tree.len[i]&1)
			node.push_back(Node(tree.len[i],tree.cnt[i]));
	sort(node.begin(),node.end());
	LL ans=1;
	for(int i=0;i<node.size();i++)
	{
		if(k>node[i].cnt)
		{
			k-=node[i].cnt;
			ans=(ans*q_pow(node[i].len,node[i].cnt))%mod;
		}
		else
		{
			ans=(ans*q_pow(node[i].len,k))%mod;
			k=0;
			break;
		}
	}
	if(k)
		ans=-1;
	printf("%lld\n",ans);
	
	
 
 
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}

 

596 original articles published, 18 praised, 20000 visitors+
Private letter follow

Posted by berry05 on Mon, 03 Feb 2020 09:08:02 -0800