24pts求调 Trie树+拓扑判环 大数据无输出
查看原帖
24pts求调 Trie树+拓扑判环 大数据无输出
465029
Specter_LiZN楼主2024/12/26 10:41

rt,样例过了,AC on #1 #5 #8,下载#2后自己跑了一遍没有输出,怀疑是数组开小了,但是 tree[1e7+5][27]tree[1e7+5][27]又超时了

注:#2 数据大小30000个字符串,而且输出也是30000个

#include <bits/stdc++.h>
#define m(i,a,b) for (int i=a;i<=b;--i)
#define f(i,a,b) for (int i=a;i<=b;++i)
#define ll long long
#define Shion cout <<"Shion is too poor to print that."<<'\n'
const signed N=300005;
const signed Miku=0x3f3f3f3f;
using namespace std;

int n,tot;
int tree[300005][27];
int ext[30005];
string s[30005];

vector <int> node[27];// 邻接表 1-26字母的树 记录规则 有环证明该字符串不能成为字典序第一 
int in[27];// 入度

queue <int> ans;
// DebugSwitch(1);

void build(string s){
  int now=0,c=0;
  int len=s.length();
  f(i,0,len-1){
    c=s[i]^96;
    if(!tree[now][c])
      tree[now][c]=++tot;
    now=tree[now][c];
  }
  ext[now]++;
  // DebugOut<<"ext "<<now<<'\n';
}
bool check(string s){
  memset(node,0,sizeof(node));
  memset(in,0,sizeof(in));
  int now=0;
  int c=0;
  int len=s.length();
  f(i,0,len-1){
    c=s[i]^96;
    if(ext[now]&&i<len-1){
      // 这意味着,有一个字符串是另一个的前缀
      // 必定失败
      // DebugOut<<"Failed at "<<s[i]<<'\n';
      return 0;
    }
    else{
      f(j,1,26){
        if(tree[now][j]&&j!=c){
          // 这意味着,有两个前缀相同的字符串
          // 此时添加规则使得本字符串字符优先于另一个
          // 即 j>c 转为 j->c          
          node[j].push_back(c);
          in[c]++;
        }
      }
    }
    now=tree[now][c];
  }
  f(i,1,26){
    if(node[i].size()){
      f(j,0,node[i].size()-1){
        // DebugOut<<(char)(i+96)<<'>'<<(char)(node[i][j]+96)<<'\n';
      }
    }
  }
  // 检查node是否有环
  vector<int> L;
  queue<int> S;
  f(i,1,26)
    if(!in[i])// 入度为0的点入队
      S.push(i);
  while (!S.empty()) {
    int u = S.front();
    S.pop();
    L.push_back(u);
    for (auto v : node[u]) {
      if (--in[v] == 0) {
        S.push(v);
      }
    }
  }
  if (L.size() == 26) {
    // for (auto i : L) // DebugOut << i << ' ';
    return 1;// 没有环
  }
  return 0;// 有环
}

signed main(){
  ios::sync_with_stdio(0),cin.tie(0);
  // init
  cin>>n;
  f(i,1,n){
    cin>>s[i];
    build(s[i]);
  }
  // check
  f(i,1,n){
    // DebugOut<<"checking "<<s[i]<<"..."<<'\n';
    if(check(s[i])){
      ans.push(i);
      // DebugOut<<"OK"<<'\n';
    }
  }
  cout<<ans.size()<<'\n';
  while(!ans.empty()){
    cout<<s[ans.front()]<<'\n';
    ans.pop();
  }
  return 0;
  Shion;
}
2024/12/26 10:41
加载中...