Submission #475267

#TimeUsernameProblemLanguageResultExecution timeMemory
475267KhaledFarhatPalindromes (APIO14_palindrome)C++14
0 / 100
57 ms60848 KiB
#include <bits/stdc++.h>
using namespace std;

struct PalindromeNode {
	PalindromeNode(int length, int suffixLink = 1)
		:	length(length), suffixLink(suffixLink), frequency(1) {
		memset(nextNode, -1, sizeof nextNode);		
	}
		
	int length;
	int suffixLink;
	int nextNode[26];
	
	int frequency;
};

struct PalindromicTree {
	PalindromicTree() 
		:	NULL_PALINDROME(0), EMPTY_PALINDROME(1),
			longestSuffixPalindrome(EMPTY_PALINDROME) {
		nodes.push_back(PalindromeNode(-1, NULL_PALINDROME));
		nodes.push_back(PalindromeNode(0, NULL_PALINDROME));
	}
	
	// return true of found a new palindrome
	bool appendLetter(char letter) {
		s += letter;
		
		int index = (int)s.size() - 1;
		int suffixLink = longestSuffixPalindrome;
		
		// searching for longest palindrome in the new suffix
		while (true) {
			int R = index;
			int L = R - nodes[suffixLink].length - 1;
						
			if (L >= 0 && s[L] == s[R]) {
				break;
			}
			else {
				suffixLink = nodes[suffixLink].suffixLink;
			}
		}
				
		// the palindrome already exists
		if (nodes[suffixLink].nextNode[letter - 'a'] != -1) {
			longestSuffixPalindrome = nodes[suffixLink].nextNode[letter - 'a'];
			++nodes[longestSuffixPalindrome].frequency;
			
			return false;
		}
		
		// found a new palindome
		int newNode = fetchNode(nodes[suffixLink].length + 2);
		
		nodes[suffixLink].nextNode[letter - 'a'] = newNode;
		longestSuffixPalindrome = newNode;
				
		// finding the suffix link of the new node
		if (nodes[newNode].length == 1) {
			nodes[newNode].suffixLink = EMPTY_PALINDROME;
		}
		else {
			while (true) {
				suffixLink = nodes[suffixLink].suffixLink;
								
				int R = index;
				int L = R - nodes[suffixLink].length - 1;
				
				if (L >= 0 && s[L] == s[R]) {
					nodes[newNode].suffixLink = nodes[suffixLink].nextNode[letter - 'a'];
					break;
				}
			}
		}
		
		return true;
	}
	
	// maintain the frequency of each palindome
	void propagate() {
		for (const PalindromeNode& palindome : nodes) {
			int parent = palindome.suffixLink;
			nodes[parent].frequency += palindome.frequency;
		}
	}

	// return the index of the new fetched node
	int fetchNode(int length) {
		nodes.push_back(PalindromeNode(length));
		
		return (int)nodes.size() - 1;
	}

	// return the index of the new fetched node
	int fetchNode(int length, int suffixLink) {
		nodes.push_back(PalindromeNode(length, suffixLink));
		
		return (int)nodes.size() - 1;
	}
	
	const int NULL_PALINDROME; // palindrome of length -1
	const int EMPTY_PALINDROME; // palindrome of length 0
	int longestSuffixPalindrome;
	vector<PalindromeNode> nodes;
	string s;
};

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	string s;
	cin >> s;
	PalindromicTree tree;
	
	for (char letter : s) {
		tree.appendLetter(letter);
	}
	
	tree.propagate();
	
	long long maxOccurrenceValue = LLONG_MIN;
	
	for (PalindromeNode& palindrome : tree.nodes) {
		long long occurrenceValue = 1LL * palindrome.length * palindrome.frequency;
				
		maxOccurrenceValue = max(maxOccurrenceValue, occurrenceValue);
	}
	
	cout << maxOccurrenceValue;
	
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...