计算按字典顺序排序的子字符串

时间:2015-03-21 06:04:50

标签: algorithm

给定长度为N的字符串S.字符串S由小写英文字母组成。我们需要计算S的许多子串被排序。

给定字符串S,我们需要计算S的排序子串数。

如果s [i]≤s[i + 1],其中1≤i≤N-1(考虑从1开始的索引),字符串s按字典顺序排序。

示例:让字符串S =" bba"然后回答是4

解释:' bba'的子字符串是:b,b,a,bb,ba,bba 在这6个子字符串中,4个(' b'' b',' a'' bb')子字符串被排序。所以答案是4。

我目前的解决方案并不比蛮力更好。那就是检查每个子字符串,然后检查它是否已排序。但是字符串长度可以是1000000,因此O(N ^ 2)方法不会成功。那么对于这个问题有什么更好的解决方案呢?

2 个答案:

答案 0 :(得分:2)

制作两个索引 - 左和右。将它们都设置为字符串的第一个符号索引。 s[Right] ≤ s[Right+1]时增量正确。
当下一个符号违反订单时,您有子串ss = s[Left..Right],所有ss的子串也被排序。
通过ss长度找到他们的号码:

k = Right - Left + 1

你有k个one-char子串,k-1个两个char字符串......和1 k长度的子字符串。

N = 1 + 2 +... + k = k * (k + 1) / 2

将N添加到susbstrings的总数,向左和向右移动(右+ 1)并继续。

答案 1 :(得分:0)

#include <bits/stdc++.h>
using namespace std;
#define ll long long int
ll sum(ll n)
{
    return (n*(n+1))/2;
}
int main()
{
    int test;
    cin>>test;
    while(test--)
    {
        int l;
        cin>>l;
        string s;
        cin>>s;
        ll ans=0, length=1;
        for(int i=1;i<s.size();i++)
        {
            //increment till it is not violating lexicographical order
            if(s[i]>=s[i-1])
                length++;
            else//store current length sum to ans and start again by setting length to one
            {
                ans+=sum(length);
                length=1;
            }

        }
        ans+=sum(length);
        cout<<ans<<endl;
    }
    return 0;
}