Trie树解法
将所有前缀插入trie树,然后根据字符串长度从小到大遍历所有前缀,然后把该字符串的最后一个字符所在结点删除,这样就可以去除所有包含当前前缀的字符串。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 20 * 50;
int tr[N][10],cnt[N], idx;
string arr[52];
int cmp(string a, string b)
{
return a.size() < b.size();
}
void insert(string s)
{
int p = 0;
for(int i = 0; i < s.size(); i++)
{
int u = s[i] - '0';
if(!tr[p][u]) tr[p][u] = ++idx;
p = tr[p][u];
}
cnt[p] = 1;
}
int query(string s)
{
int p = 0;
for(int i = 0; i < s.size(); i++)
{
int u = s[i] - '0';
if(!tr[p][u]) return 0;
p = tr[p][u];
}
return cnt[p];
}
void del(string s)
{
int p = 0, x = s[s.size()-1]-'0';
for(int i = 0; i < s.size()-1; i++)
{
int u = s[i] - '0';
p = tr[p][u];
}
cnt[p] = 0;
tr[p][x] = 0;
}
int main()
{
long long n, m;
cin>>n>>m;
for(int i = 0; i < m; i++)
{
cin>>arr[i];
insert(arr[i]);
}
sort(arr, arr+m, cmp);
long long res = pow(10, n);
for(int i = 0; i < m; i++)
{
if(query(arr[i]))
{
del(arr[i]);
//cout<<arr[i]<<endl;
long long temp = pow(1ll*10, 1ll*n-arr[i].size());
//cout<<res<<" "<<pow(10, 1ll*n-arr[i].size())<<" ";
res = res - temp;
//cout<<res<<endl;
}
}
cout<<res;
}