- POJ 3096 - Surprising Strings
- Time: 1000MS
- Memory: 65536K
- 难度: 中级
- 分类: 基础算法
问题描述
定义D-pairs表示取字符串s中相距为D的两个字母所构成的字母对,该字母对中两个字母的位置顺序与他们在主串s中的位置顺序一致
定义D-unique表示,若从字符串s中取出所有相距为D的字母对D-pairs,且这些D-pairs都是独一无二的,那么成字符串s是一个D-unique串
D的取值范围为 0 ~ s.len()-2
假如字符串s对于所有的D都有D-unique成立,则字符串s是令人惊讶的
现在输入一些字符串,问他们能不能令人惊讶
解题思路
令人惊讶的中级水题= =
用STL的map标记D-unique是否重复出现就OK了
也可以用ASCII标记,取两个大写字母的ASCII构成一个四位数作为key就可以了,比map快一点点
层次关系:
- 对于某个D,当所有D-pairs都不同时,s是D-unique
- 对于所有D,s都有D-unique时,它是surprising string
注意:
- 长度小于等于2的s都是surprising string
- 其实我感觉这题暴力也能AC= =,S最大长度也就79…
AC 源码
解题方法一:STL<map>标记
/*STL<map>标记*/
//Memory Time 
//212K   16MS 
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(void)
{
    char s[80];
    while(cin>>s && s[0]!='*')
    {
        int len=strlen(s);
        if(len<=2)  //长度小于等于2的串必定是surprising String
        {
            cout<<s<<" is surprising."<<endl;
            continue;
        }
        bool mark=true;  //标记s是否为Surprising String
        for(int d=0;d<=len-2;d++)  //d为当前所选取的两个字母之间的距离,d(max)=len-2
        {
            map<string,bool>flag;
            bool sign=true;  //标记D-pairs字母对是不是D-unique
            for(int i=0;i<=len-d-2;i++)  //i为所选取的两个字母中第一个字母的下标
            {
                char pair[3]={s[i],s[i+d+1],'\0'};  //构成D-pairs字母对
                if(!flag[ pair ])
                    flag[ pair ]=true;
                else
                {
                    sign=false;  //存在相同的D-pairs,该字母对不是D-unique
                    break;
                }
            }
            if(!sign)
            {
                mark=false;  //存在非D-unique,s不是Surprising String
                break;
            }
        }
        if(mark)
            cout<<s<<" is surprising."<<endl;
        else
            cout<<s<<" is NOT surprising."<<endl;
    }
    return 0;
}解题方法二:ASCII标记
/*ASCII标记*/
//Memory Time 
//212K   0MS 
#include<iostream>
#include<string>
using namespace std;
int main(void)
{
    char s[80];
    while(cin>>s && s[0]!='*')
    {
        int len=strlen(s);
        if(len<=2)  //长度小于等于2的串必定是surprising String
        {
            cout<<s<<" is surprising."<<endl;
            continue;
        }
        bool mark=true;  //标记s是否为Surprising String
        for(int d=0;d<=len-2;d++)  //d为当前所选取的两个字母之间的距离,d(max)=len-2
        {
            bool flag['Z'*100+'Z'+1];   //标记D-pairs字母对
            memset(flag,false,sizeof(flag));
            bool sign=true;  //标记D-pairs字母对是不是D-unique
            for(int i=0;i<=len-d-2;i++)  //i为所选取的两个字母中第一个字母的下标
            {
                int pair=s[i]*100+s[i+d+1];  //D-pairs字母对的ASCII码所构成的四位数
                if(!flag[pair])
                    flag[pair]=true;
                else
                {
                    sign=false;  //存在相同的D-pairs,该字母对不是D-unique
                    break;
                }
            }
            if(!sign)
            {
                mark=false;  //存在非D-unique,s不是Surprising String
                break;
            }
        }
        if(mark)
            cout<<s<<" is surprising."<<endl;
        else
            cout<<s<<" is NOT surprising."<<endl;
    }
    return 0;
} 
                     
                     
                     
                        
                        