计算字符串中的字母序列 - C ++

时间:2015-01-23 19:54:09

标签: c++ encryption counter frequency-analysis

我正在研究一种简单的替换密码解码器。我正在使用频率分析来解密密文。只看独特字母的频率是不够的。我需要看一下2个字母的序列(可能是3个字母的序列)。

我计算每个字母出现次数的代码低于

int counterRaw[256][2] = {0};
    for(int i = 0; i <inputString.length(); i++)
        counterRaw[inputString[i]][1]++;

int counterLetter[26][2] = {0};
    for(int i = 0 ; i<26 ; i++){
        counterLetter[i][0] = 'A'+i;
        counterLetter[i][1] = counterRaw['A'+i][1];

你可以看到非常简单但有效!

但我不知道如何实现2个字母的序列计数器,你有什么想法可以帮我编码吗?

谢谢!

编辑:举个例子 鉴于AZAZ RTYU JKLM我希望我的程序输出:

AZ : 2
ZA : 1
ZR : 1
RT : 1
...

4 个答案:

答案 0 :(得分:1)

你应该用两个字母创建一个“复合字母”。 由于C,C ++中的字母是数字,您只需将2个字母中的每个字母转换为数字(字符已经是数字),然后创建带有两个数字的数字。例如int C = inputString [i] + 256 * inputString [i + 1]。 上面假设字符串是char和chars,介于0到255之间(优于签名)。

答案 1 :(得分:0)

你现在正在做的是计算排序。 如果考虑多个数字,基数排序将是一个可行的选择。

答案 2 :(得分:0)

在这里(基于user3723779的想法):

#define MAKEWORD(a, b) (((a) << 8) | (b))

std::string noSpaces(std::string s)
{
    int pos;
    while((pos = s.find(' ')) != std::string::npos)
    {
        s.erase(pos, 1);
    }
    return s;
}

std::map<short, int> seqDet2(const std::string &s)
{
    int length = s.length();
    if(length == 0) return std::map<short, int>();

    // assert(sizeof(char) == 1);
    std::vector<short> v;

    for(int i = 0; i < length - 1; ++i)
    {
        v.push_back(MAKEWORD(s[i], s[i + 1]));
    }

    std::map<short, int> occ;
    for(auto x: v)
    {
        occ[x]++;
    }

    return occ;
}

int main()
{
    std::string s = "AZAZRTYUI AZTWI";
    auto occ = seqDet2(noSpaces(s));

    for(auto x: occ)
    {
        unsigned char b = (unsigned char)x.first;
        unsigned char a = (unsigned char)(x.first >> 8);
        printf("%c%c - %d\n", a, b, x.second);
    }

    getchar();
}

答案 3 :(得分:0)

像下面这样的东西可以解决这个问题,尽管你必须做一些jiggery pokery才能满足你自己的需要。

#include <iostream>
#include <map>
#include <string>

int main ()
{
    std::string message("some string that you will probably get from some encrypted file");
    std::map<std::string,int> occurences;

    std::string seq("  ");
    for(int i = 1; i < message.length() - 1; i++)
    {
        seq[0] = message[i-1];
        seq[1] = message[i];

        //ignore spaces
        if (seq.compare(0,1, " ") && seq.compare(1,1, " "))
        {
            occurences[seq]++;
        }
    }

    //let's have a look ...
    for(auto iter = occurences.begin(); iter != occurences.end(); ++iter)
    {
        std::cout << iter->first << "   " << iter->second << "\n";
    }
    return 0;
}

输出:

ab   1
at   1
ba   1
bl   1
cr   1
ed   1
en   1 
et   1
fi   1
fr   1
ge   1
ha   1
il   2
in   1
ll   1
ly   1
me   2
nc   1
ng   1
ob   1
om   3
ou   1
pr   1
pt   1
ri   1
ro   2
ry   1
so   2
st   1
te   1
th   1
tr   1
wi   1
yo   1
yp   1