您的位置:首页 > 其它

无分隔符字典问题

2015-11-26 10:46 776 查看
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
using namespace std;

int *ak;
int lk;
int n, k;
int best = 0; //最大无分隔符字典元素个数

vector<int> L;  //将所有的长度为k的数字字符串存到集合L中
set<int> S;  //当前字典中的字符串存储在集合s中

//将下标为L[]中下标为i的字符串存入集合s
void insert(int i)
{
S.insert(L[i]);
}

//将下标为L[]中下标为i的字符串存入集合s
void erase(int i)
{
S.erase(L[i]);
}

//将ak[]中起点为i-1,长度为k-1数字串转换为十进制数字
int digi(int i)
{
int ii = k + i - 2;
int x = ak[ii--];
for(int j=0; j<k-1; j++)
{
x *= 10;
x += ak[ii];
ii--;
}
return x;
}

//判断字符串a和第b个字符串是否互不为前缀
bool pref(int a, int b)
{
int bb = L[b];
int x = a;
int y = bb/n;  //去掉最高位,得到低k-1位
for(int i=0; i<k-1; i++) //ak[0, k-2]存放x的低k-1位,ak[k-1, k-1 + (k-2)]存放y
{
ak[k-i-2] = x % n;
x /= n;
ak[2*k-i-3] = y % n;
y /= n;
}
for(i=1; i<k; i++) //相当于依次判断a2a3..akb1, a3a4..b1b2, akb1..bk-1是否已存在于S中,本程序中下标从0开始
if(S.count(digi(i)) > 0)  //如果已存在于S中
return true;

x = bb;
y = a/n;
for(i=0; i<k-1; i++)
{
ak[k-i-2] = x % n;
x /= n;
ak[2*k-i-3] = y % n;
y /= n;
}
for(i=1; i<k; i++)
if(S.count(digi(i)) > 0)
return true;

return false;
}

//判断当前下标为b的字符串是否可以加入字典
//将字符串a1a2..ak看作k位十进制数
bool oka(int b)
{
int bb = L[b];
set<int>::iterator it;  //定义迭代器
it = S.begin();
while(it != S.end())
{
int a = *it;
if(pref(a, bb)) //如果a,b其中一个是另一个的前缀
return false;
it++;
}
return true;
}

//得到总元素个数为n,长度为m的全排列
void Perm(int list[], int dep, int m, int n)
{
if(dep>m)
{
int x = 0;
for(int i=1; i<=m; i++)
x = x*10 + list[i];   //转换为十进制数字
L.push_back(x);  //将所有的数字字符串存到集合L中

}
else
for(int j=1;j<=n;j++)
{
swap(list[dep], list[j]);
Perm(list, dep+1, m,  n);
swap(list[dep], list[j]);
}
}

void backtrack(int dep)
{
if(dep >= lk)
{
if(S.size() > best)
best = S.size();
return;
}
if(oka(dep))
{
insert(dep);
backtrack(dep+1);
erase(dep);
}
backtrack(dep+1);
}

int main()
{
ifstream fin("无分隔符字典.txt");
cout << "输入正整数n:";
fin >> n; cout << n;
cout << "\n输入正整数k:";
fin >> k; cout << k;
ak = new int[2*k];
lk = n;
for(int i=1; i<k; i++) //k个字符中,每一个字符都有n种选择,n^k表示所有由k个字符组成的字符串种数
lk *= n;
lk--;

int *x = new int[n+1];
for(i=1; i<=n; i++)
x[i] = i;
Perm(x, 1, k, n); //将长度为k的全排列存入集合L中
backtrack(0);
cout << "\n最大无分隔符字典元素个数为:" << best;

cout << endl;
cout << endl;
fin.close();
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: