Atcoder Grand Contest 019 B题解

Atcoder Grand Contest 019 B题解

题意

给定一个由小写英文字母组成的序列,可以选择i和j然后将AiAi+1…Aj反转,反转最多一次,问一共能得到多少不同的序列。

笺释

首先,什么都不做的时候是一个序列。
然后从头开始,第一个字母不可能与任何字母颠倒,此时无法以任何方式得到新序列。
对于第二个字母,显然,如果他和第一个字母不同,那么将这两个颠倒得到一个新序列,如果相同的话,仍然得不到新序列。
对于第三个字母,如果他和第二个字母不同,可以颠倒得到新序列,如果相同,得不到新序列。如果他和第一个字母不同,可以颠倒得到新序列,如果相同,得不到新序列。
可能考虑到有这种情况:
一个字母尽管与前面某个字母相同,但是他中间的字母有所不同,那么尽管相同,将这个字母与前面某个字母颠倒仍然得到新序列。这似乎说明不能通过某个字母是否与前边某个字母相同与否判断是否增加新序列数目。
比如说atba,第四个字母a和第一个字母a相同,但是将第四个和第一个颠倒是可以得到新序列abta的。
但是实际上,abta这个序列已经通过在第三个字母那里判断b和t是否相同的时候计入新序列数了。
从根本上来说,我觉得这是一个很好的动态规划思想应用,我们每一次拿到一个新字母实际上是在考虑在上一次的基础上还能否扩展不同的序列,而扩展的方法只有判断是否有不同的字母而已,至于上一次所包括的字母里是否有不同的,那已经在上一次判断过了。

完整代码

#include
#define MAXN 200005
using namespace std;
char str[MAXN];
int alp[27];
long long ans;
int main()
{
    scanf("%s",str+1);
    int n=strlen(str+1);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=25;j++)
        {
            if(j==(str[i]-'a'))
            {
                continue;
            }
            else
            {
                ans+=alp[j];
            }
        }
        alp[str[i]-'a']++;
    }
    printf("%lld\n",ans+1);
}

你可能感兴趣的:(Atcoder Grand Contest 019 B题解)