Я работаю над простым зашифровывающим декодером. Я использую частотный анализ для расшифровки зашифрованного текста. Просто смотреть на частоту уникального письма недостаточно. Мне нужно взглянуть на появления двухбуквенных последовательностей (возможно, трехбуквенных последовательностей).
Мой код для подсчета вхождений каждой буквы ниже
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];
Как видите, очень просто, но эффективно!
Но я не знаю, как получить двухбуквенный счетчик последовательности, есть ли у вас какие-либо идеи, которые могли бы помочь мне закодировать это?
Спасибо !
РЕДАКТИРОВАТЬ: В качестве примера
Учитывая AZAZ RTYU JKLM, я хочу, чтобы моя программа выводила:
AZ : 2
ZA : 1
ZR : 1
RT : 1
...
Что-то вроде следующего поможет, хотя вам нужно будет поиграть, чтобы он соответствовал вашим собственным потребностям.
#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
Вы должны создать «составное письмо» из двух букв.
Поскольку буквы в C, C ++ являются числами, вы можете просто преобразовать каждую из двух букв в число (символы уже являются числами), а затем создать число с двумя числами. например int C = inputString [i] + 256 * inputString [i + 1].
Выше с предположением, что строки имеют тип char, а символы между 0 и 255 (лучше, чем со знаком).
То, что вы делаете сейчас, — это подсчет.
Радикальная сортировка была бы жизнеспособным вариантом для вас, если принять во внимание несколько цифр.
Вот, пожалуйста (основано на идее 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();
}