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; }