生成英文回文串

生成英文回文串

Description

考虑有许多词语,现在希望找出所有三元组, 满足三元组内的词能够拼接成一个回文。 每一行, 按照拼接的顺序依次输出它们原来的位置,不同的行对应不同的三元组,输出时候要按从小到大顺序依次输出所有能够组成回文三元组的。考虑两个不同三元组A={a1,a2,a3},B={b1,b2,b3} (ai, bi是对应单词在输入单词序列中的序号),三元组的大小指的是第一个不同元素的先后顺序,优先输出第一个不同元素靠前那个三元组。即A < B 等价于“对下标k = min{i | ai ≠ bi}, ai < bi”.

假设没有重复的字符串,请不要输出重复的三元组,也不要漏掉任何一个满足条件的三元组;每行输出三元组顺序时候,三元组每个词的位置是从 0 开始。

Input Description

第一行输入字符串个数 N 和字符串最大长度 L, 后面 N 行输入对应 N 个字符串。

Output Description

第一行输出能够组成回文的三元组个数 M,后面 M 行依次输出满足条件的三元组。每 一行输出三元组中每个词的原位置。不同的行代表不同三元组,按照三元组的先后顺序输出, 三元组的先后顺序指的是不同三元组第一个不同的词语原位置的先后顺序,应该优先输出第 一个不同词语靠前的三元组。

Input Sample

20 10
ccfea
eeab
ccd
dd
abdeb
ffbf
ef
aeff
baee
cae
adbac
cab
fa
dcb
bdf
fce
cbae
fed
fb
edcf

Output Sample

4
1 3 8
8 3 1
17 2 6
17 3 6

Idea

用哈希表存储位置,键值为字符串。先任意找两个词合并, 然后找第三个词, 让它们组合成回文串。找第三个词时,需要将组合串比第三个词长还是短分开处理。每个组合串先翻转,再从头到尾和从尾到头扫描两遍,寻找回文子串,则剩余部分就是要找的第三个词。

Code

#include<iostream>
#include<string>
#include<tr1/unordered_map>
#include<vector>
#include<algorithm>
using namespace std;
struct result{                            //存储找到的三元组的三个标号
    int a,b,c;
};
vector<result*>output;                    //存储所有满足条件的三元组
bool judge(string str_sub){               //判断给定的字符串是否是回文  
    int len=str_sub.length();
    int i=0,j=len-1;
    while(j>=i){
        if(str_sub[i]!=str_sub[j])
            return false;
        i++;j--;
    }
    return true;
}                                          
void Seek(std::tr1::unordered_map<string,int> &word,string &w1,string &w2){
    string str_plus=w1+w2;
    int len=str_plus.length();
    string str_reverse(len,'a');
    for(int i=0;i<len;i++)
        str_reverse[i]=str_plus[len-1-i];
    std::tr1::unordered_map<string,int>::iterator seek;
    seek=word.find(str_reverse);                    //先寻找整体组成的字符串
    if(seek!=word.end()){
        result *newr=new result;
        newr->a=word[w1];
        newr->b=word[w2];
        newr->c=word[str_reverse];
        output.push_back(newr);
    }
    for(int i=0;i<len-1;i++){                       //再寻找从头到尾扫描可能存在的字符串
        string str_sub=str_reverse.substr(0,i+1);
        if(judge(str_sub)){
            string str_seek=str_reverse.substr(i+1,len-i-1);
            seek=word.find(str_seek);
            if(seek!=word.end() && str_seek!=w1 && str_seek!=w2){
                result *newr=new result;
                newr->a=word[w1];
                newr->b=word[w2];
                newr->c=(*seek).second;
                output.push_back(newr);
            }
        }
    }
    for(int i=len-1;i>=1;i--){                      //再寻找从尾到头扫描可能存在的字符串
        string str_sub=str_reverse.substr(i,len-i);
        if(judge(str_sub)){
            string str_seek=str_reverse.substr(0,i);
            seek=word.find(str_seek);
            if(seek!=word.end() && str_seek!=w1 && str_seek!=w2 
               && (*seek).first.length()+w1.length()<w2.length()){
                result *newr=new result;
                newr->a=(*seek).second;
                newr->b=word[w1];
                newr->c=word[w2];
                output.push_back(newr);
            }
        }
    }
}
bool cmp(result* x,result* y){           //sort函数需要用的比较函数,按标号升序排列
    if(x->a!=y->a)
        return x->a<y->a;
    if(x->b!=y->b)
        return x->b<y->b;
    if(x->c!=y->c)
        return x->c<y->c;
}
int main(){
    int N,L;
    cin>>N>>L;
    string str;
    string *all=new string[N];
    std::tr1::unordered_map<string,int>word;                //哈希表word存储N个字符串
    for(int i=0;i<N;i++){
        cin>>str;
        all[i]=str;
        word[str]=i;
    }
    for(int i=0;i<N;i++)           
        for(int j=0;j<N;j++){      //遍历哈希表,任意两个字符串相加
            if(i!=j)
                Seek(word,all[i],all[j]);
        }
    int size=output.size();
    cout<<size<<endl;
    if(size!=0){
        sort(output.begin(),output.end(),cmp);     //对所有三元组按标号排序
        for(int i=0;i<size;i++)                  
            cout<<output[i]->a<<" "<<output[i]->b<<" "<<output[i]->c<<endl;
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值