給定兩個字串 a 和 b,求下面四個問題的答案:
1.在 a 的子串中,不是 b 的子串的字串的數量。
2.在 a 的子串中,不是 b 的子串行的字串的數量。
3.在 a 的子串行中,不是 b 的子串的字串的數量。
4.在 a 的子串行中,不是 b 的子串行的字串的數量。
其中子串是指本質不同的子串,不同的位置相同的串也只算乙個串
|s|<=2000
構造倆自動機然後同時跑
構造乙個子串行自動機,再構造乙個字尾自動機,然後從根依次轉移,記錄狀態上的資訊,記憶化一下。
#include using namespace std;
const int mo=1e9+7, lim=100005;
int nid;
struct node
}po[lim], *it=po, *root[2], *last[2], *rt[2];
node *newnode()
void init()
void add1(int who, int ch)
if(!now)
node *y=now->c[ch];
if(y->len==now->len+1)
node *z=newnode();
*z=*y;
z->id=nid++;
z->len=now->len+1;
x->f=y->f=z;
for(; now && now->c[ch]==y; now=now->f)
}void cal(node *x)
x->flag=1;
x->s=1;
for(int ch=0; ch<26; ++ch)
} }}void build1(int who, char *s)
cal(root[who]);
}void build2(int who, char *s)
tc[*s-'a']=now;
} for(int ch=0; ch<26; ++ch)
cal(rt[who]);
}int vis[5005][5005];
int getans(node *x, node *y)
if(!y)
if(vis[x->id][y->id]!=-1)
int ret=0;
for(int ch=0; ch<26; ++ch)
} return vis[x->id][y->id]=ret;
}char s[2][2005], *it[2];
int main()
build2(0, it[0]);
build2(1, it[1]);
memset(vis, -1, sizeof vis); printf("%d\n", getans(root[0], root[1]));
memset(vis, -1, sizeof vis); printf("%d\n", getans(root[0], rt[1]));
memset(vis, -1, sizeof vis); printf("%d\n", getans(rt[0], root[1]));
memset(vis, -1, sizeof vis); printf("%d\n", getans(rt[0], rt[1]));
return 0;
}
弱省互測 0 t1
給乙個 n times m 的01網格,1不能走,從起點 1,1 走到 n,m 每次只能向下或向右走一格,問兩條不相交的路徑的方案數。n,m 1000 先考慮一條,再考慮去掉相交的情況。令 d a,b,c,d 表示從 a,b 走到 c,d 一條路徑的方案數,則可以簡單得到答案 ans d 2,1,n...
弱省互測 0 t3
要求給出下面 的答案然後構造輸入。給乙個圖,n 個點 m 條邊 q 次詢問,輸出所有點對之間最大權值最小的路徑。把每乙個詢問的輸出看成一條邊,建一棵最小生成樹。給輸出,要求構造輸入使得用所給 執行後得到的輸出和給出的輸出相同。所給 n 次 dijkstra 求兩點間最短路 考慮一下貪心。首先還是把每...
弱省互測 2 t2
給兩個樹,大小分別為n和m,現在兩棵樹各選一些點 包括1 使得這棵樹以1號點為根同構 同構就是每個點的孩子數目相同 求最大的同構樹。n,m 500 我們從兩棵樹中各取出乙個點,考慮以這兩個點為根能得到的最大同構數。容易得到 設 d i,j 表示第一棵樹選 i 號點,第二棵樹選 j 號點所能得到的最大...