回文排列子串

时间:2019-12-08 08:43:08

标签: substring dynamic-programming palindrome

在HackerEarth测试中我被问到了这个问题,我什至无法形成算法。

问题是-

Count the number of substrings of a string, such that any of their permutations is a palindrome.

因此,对于aab,答案是5-aabaaaab (可以排列成aba的形式。)

我觉得这是动态编程,但是我找不到子问题可能具有什么样的关系。

编辑: 所以我认为递归关系可能是

dp[i] = dp[i-1] + 1 if str[i] has already appeared before and 
        substring ending at i-1 has at most 2 characters with odd frequency
else dp[i] = dp[i-1]

不知道这是否正确。

4 个答案:

答案 0 :(得分:0)

如果我没有误解你的问题,我倾向于认为这是一个数学问题。假设字符串的长度为n,则答案应为n *(n + 1)/ 2,即无穷级数之和。参见https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF

例如,字符串abcde,我们可以获取子字符串
abcde
abbccdde
abcbcdcde
abcdbcde
abcde
您可能会从我列出子字符串的方式中找到答案。

答案 1 :(得分:0)

我可以想到O(n^2)-遍历长度大于1的子字符串,从索引(0,1)到(0,n-1),然后从(1,n-1)向下到(1 ,3),然后从(2,3)到(2,n-2),然后从(3,n-2)向下到(3,5)...等。

遍历时,维护每个字符的当前频率图,以及具有奇数计数的字符数和具有偶数计数的字符数的总和。如果我们使用的子串的长度为(1)个奇数长度且只有一个字符具有奇数频率,或者是(2)个偶数长度且无字符具有奇数频率,则在每次迭代时更新这些值并添加回文排列子串的总数。 >

(为单字符回文计数添加字符串长度。)

答案 2 :(得分:0)

所以这是我的解决方案,可以为您提供帮助。

通过运行嵌套循环,可以获得输入的每个可能子串的列表,对于每个子串,您都必须检查子串是否可以形成回文。

现在如何检查字符串/子字符串是否可以形成回文:

如果子字符串的出现次数的奇数字母大于1,则它们不能形成回文。代码如下:

布尔字符串CanbeFormAPalindrome(字符串s)     {     int奇数值,字母[26];

for(int i =0; i< s.length(); i++)
{
    alphabet[s[i]-'a']++;
}

for(int i=0; i<26; i++)
{
    if(alphabet[i]%2==1)
    {
        oddValues++;

        if(oddValues>1) return FALSE;
    }
}

return TRUE;   
}

希望有帮助。

答案 3 :(得分:0)

您可以在 O(N) 时间和 O(N) 空间复杂度内轻松完成

请注意,如果子串的排列是否为回文,唯一的问题是其中奇数字符的奇偶校验,因此只需创建每个字符的奇偶校验掩码,现在对于任何有效子串,最多可以有 1 位不同对我们当前的掩码,让我们迭代哪个位不同,并添加相应的答案。

这是一个 C++ 代码(假设 unordered_map 是每个查询的 O(1))

    string s;
    cin>>s;
    int n=s.length();
    int ans=0;
    unordered_map<int,int>um;
    um[0]=1;
    int mask=0;
    for(int i=0;i<n;++i){
        mask^=1<<(s[i]-'a');
        ans+=um[mask];
        for(int j=27;j>=0;--j){
            ans+=um[mask^(1<<j)];
        }
        um[mask]++;
    }
    cout<<ans;

注意整数溢出。