给定长度为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)方法不会成功。那么对于这个问题有什么更好的解决方案呢?
答案 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;
}