每个串拆成两个,都插入trie数。
把trie树建出来后,每一条从根到叶子的链上最多只能有一个变量为1。 这是个经典的前后缀优化2-sat建图的套路。 树上的做法也就是边dfs边做而已。#include#define N 3300000#define eps 1e-7#define inf 1e9+7#define db double#define ll long long#define ldb long doubleusing namespace std;inline int read(){ char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*flag;}struct edge{int to,nxt;}e[N*4];int num,head[N];inline void add(int x,int y){e[++num]=(edge){y,head[x]};head[x]=num;}stack st;bool in_stack[N];int times,bel_cnt,dfn[N],low[N],bel[N];void tarjan(int x){ dfn[x]=low[x]=++times; st.push(x);in_stack[x]=true; for(int i=head[x];i!=-1;i=e[i].nxt) { int to=e[i].to; if(!dfn[to])tarjan(to),low[x]=min(low[x],low[to]); else if(in_stack[to])low[x]=min(low[x],dfn[to]); } if(dfn[x]==low[x]) { bel_cnt++; int u; do { u=st.top();st.pop(); bel[u]=bel_cnt; in_stack[u]=false; }while(x!=u); }}char s[N];int size,f[N],p[N],pre[N];struct Trie{ #define lson son[x][0] #define rson son[x][1] #define mid ((l+r)>>1) vector v[N]; int root=1,cnt=0,tot=1,son[N][2]; void insert(int n,int id) { int x=root; for(int i=1;i<=n;i++) { int k=s[i]-'0'; if(!son[x][k])son[x][k]=++tot; x=son[x][k]; } v[x].push_back(id); } void dfs(int x) { int len=v[x].size(); for(int i=0;i